我正在尝试实现订阅模型。如果一个创建者采取了行动,则创建者的订阅者应收到通知。我是这样制作模型的:
class Notification(models.Model):
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(default=timezone.now, db_index=True)
creator = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, related_name='notification_creator')
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, related_name='notification_receiver')
post = models.OneToOneField(forum_models.Post, null=True, on_delete=models.CASCADE, related_name='notification')
comment = models.OneToOneField(forum_models.Comment, null=True, on_delete=models.CASCADE, related_name='notification')
channels = models.ManyToManyField(forum_models.Channel, related_name='notifications')
class Meta:
ordering = ['-updated_date', '-id']
可以从创建者向创建帖子或评论的收件人发出简单通知。但是,当我想通知所有订阅创建者频道的接收者时,出现了问题。每当创建者执行某项操作时,我必须为每个接收者创建一个通知。这就是我从django-notification中找到的。我得出结论,这是一种传递通知的非常低效的方式,因此我创建了另一个模型。
class NotificationListner(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='notification_listners_receiver')
channel = models.ForeignKey(forum_models.Channel, null=True, on_delete=models.CASCADE, related_name='notification_listners')
following = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, related_name='notification_listeners')
notify = models.BooleanField(default=False)
为每个接收者创建一个通知侦听器,用于订阅频道或后续人员。我这样查询:
def resolve_notifications(self, info, **kwargs):
return models.Notification.objects.filter(
Q(Q(channels__notification_listners__receiver=info.context.user) & Q(post__is_null=False) & Q(notify=True)) |
Q(creator__notification_listeners__receiver=info.context.user) |
Q(receiver=info.context.user)
)
def resolve_unread_notification_count(self, info, **kwargs):
return Notification.objects.filter(
Q(Q(Q(channels__notification_listners__receiver=info.context.user) & Q(post__is_null=False) & Q(notify=True)) |
Q(creator__notification_listeners__receiver=info.context.user) |
Q(receiver=info.context.user)) & Q(updated_date__gt=info.context.user.lastCheckedDate)
).count()
通过这种方式,我可以创建频道数*接收者数,而不是频道数*接收者数*通知数
同样,我必须实现消息传递功能,但是我发现必须为每个用户的每个消息创建一个通知。为了解决这个问题,我创建了另一个侦听器模型。
class Room(models.Model):
name = models.CharField(max_length=100)
participants = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='message_participants', blank=True)
# Room.objects.filter(participants__receiver=info.context.user)
def get_unread_messages(self, user):
room_listener = self.room_listeners.get(receiver=user)
self.messages.filter(id__gt=room_listener.lastCheckedMessage.id).count()
def get_last_message(self):
message = Message.objects.filter(room=self).last()
return message.text
def get_last_message_timestamp(self):
message = Message.objects.filter(room=self).last()
return message.timestamp
def __str__(self):
return self.name
class Message(models.Model):
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name="messages")
sender = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
text = models.TextField(blank=True)
timestamp = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta:
ordering = ['timestamp']
class RoomListener(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='room_listners')
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name='room_listeners')
lastCheckedMessage = models.ForeignKey(Message, null=True, on_delete=models.SET_NULL)
通过这种方式,我不需要为#条消息*#名参与者创建unread_flags,而是为#个房间*#名参与者创建总的房间侦听器。
但是我无法在互联网上找到任何进一步的例子,我想知道是否还有一些我想念的东西。我对现实世界中的消息传递应用程序如何处理此问题感到好奇。有没有比我现在做的更好的方法?