在订阅模型上传递大量通知和消息

时间:2019-07-13 13:31:11

标签: django django-models

我正在尝试实现订阅模型。如果一个创建者采取了行动,则创建者的订阅者应收到通知。我是这样制作模型的:

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,而是为#个房间*#名参与者创建总的房间侦听器。

但是我无法在互联网上找到任何进一步的例子,我想知道是否还有一些我想念的东西。我对现实世界中的消息传递应用程序如何处理此问题感到好奇。有没有比我现在做的更好的方法?

0 个答案:

没有答案