Python 保存通知对象django websockets的逻辑

Python 保存通知对象django websockets的逻辑,python,django,django-views,django-channels,Python,Django,Django Views,Django Channels,在一个双人Django频道websockets聊天应用程序中,当从另一个other_用户收到消息时,我很难思考如何保存通知 现在我有一个函数def create_notification,在def create_chat_message之后调用 def create_chat_message每次在线程中发送新消息时,都会创建一个新的ChatMessage对象。它需要argsthread=thread\u obj,user=me,message=msg,因此显然每个消息都是与用户一起保存的,而不是

在一个双人
Django频道
websockets聊天应用程序中,当从另一个
other_用户
收到消息时,我很难思考如何保存通知

现在我有一个函数
def create_notification
,在
def create_chat_message
之后调用

def create_chat_message
每次在
线程中发送新消息时,都会创建一个新的
ChatMessage
对象。它需要args
thread=thread\u obj,user=me,message=msg
,因此显然每个消息都是与用户一起保存的,而不是发送的

def create_notification
通过
ChatMessage
中的
id
获取最后一个对象,并创建一个新的
notification
对象

created_notification = Notification.objects.create(notification_user=user, notification_chat=last_chat)
因此,从本质上讲,发送消息的人与
notification
模型中的
notification\u user
字段相关联,并与
ChatMessage
id一起保存

但是,如果我向Tom发送消息,我发送的消息应该只与Tom的通知关联,而不是我自己

当我去渲染通知对象时,我会得到所有这些对象的列表,包括我发送的消息的通知

我如何为我与不同用户在一起的每个线程呈现所有通知

我把这些存错了吗?我是否应该配置保存通知功能,使其仅保存来自其他用户的传入消息?或者添加某种类型的
if语句

我是否需要以某种方式与通知相关联,以便当它们呈现出来时,我作为收件人的所有通知都会显示出来

我的
通知
模型将
聊天信息
作为
外键
,它有一个
线程
字段,这是一个
外键
线程
,它包含
第一个
第二个
(在一个线程中代表我和另一个用户)

我已经看了好几天了,有种感觉我错过了一些简单的东西,让事情变得比需要的复杂得多

models.py

class ThreadManager(models.Manager):
    def by_user(self, user):
        qlookup = Q(first=user) | Q(second=user)
        qlookup2 = Q(first=user) & Q(second=user)
        qs = self.get_queryset().filter(qlookup).exclude(qlookup2).distinct()
        return qs

    # method to grab the thread for the 2 users
    def get_or_new(self, user, other_username): # get_or_create
        username = user.username
        if username == other_username:
            return None, None
        # looks based off of either username
        qlookup1 = Q(first__username=username) & Q(second__username=other_username)
        qlookup2 = Q(first__username=other_username) & Q(second__username=username)
        qs = self.get_queryset().filter(qlookup1 | qlookup2).distinct()
        if qs.count() == 1:
            return qs.first(), False
        elif qs.count() > 1:
            return qs.order_by('timestamp').first(), False
        else:
            Klass = user.__class__
            try:
                user2 = Klass.objects.get(username=other_username)
            except Klass.DoesNotExist:
                user2 = None
            if user != user2:
                obj = self.model(
                        first=user,
                        second=user2
                    )
                obj.save()
                return obj, True
            return None, False

class Thread(models.Model):
    first        = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
    second       = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
    updated      = models.DateTimeField(auto_now=True)
    timestamp    = models.DateTimeField(auto_now_add=True)

    objects      = ThreadManager()

    def __str__(self):
        return f'{self.id}'

    @property
    def room_group_name(self):
        return f'chat_{self.id}'

    def broadcast(self, msg=None):
        if msg is not None:
            broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
            return True
        return False

class ChatMessage(models.Model):
    thread      = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL)
    user        = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='sender', on_delete=models.CASCADE)
    message     = models.TextField()
    timestamp   = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.id}'

class Notification(models.Model):
    notification_user = models.ForeignKey(User, on_delete=models.CASCADE)
    notification_chat = models.ForeignKey(ChatMessage, on_delete=models.CASCADE)
    notification_read = models.BooleanField(default=False)

    def __str__(self):
        return f'{self.id} attached to {self.notification_user}'
消费者.py

class ChatConsumer(AsyncConsumer):
    async def websocket_connect(self, event):
        print('connected', event)

        other_user = self.scope['url_route']['kwargs']['username']
        me = self.scope['user']
        #print(other_user, me)
        thread_obj = await self.get_thread(me, other_user)
        self.thread_obj = thread_obj
        chat_room = f"thread_{thread_obj.id}"
        self.chat_room = chat_room
        # below creates the chatroom
        await self.channel_layer.group_add(
            chat_room,
            self.channel_name
        )

        await self.send({
            "type": "websocket.accept"
        })

    async def websocket_receive(self, event):
        # when a message is recieved from the websocket
        print("receive", event)

        message_type = json.loads(event.get('text','{}')).get('type')
        print(message_type)
        if message_type == "notification_read":
            user = self.scope['user']
            username = user.username if user.is_authenticated else 'default'
            # Update the notification read status flag in Notification model.
            notification = Notification.objects.filter(notification_user=user)
            notification.notification_read = True
            notification.save()  #commit to DB
            print("notification read")
            return

        front_text = event.get('text', None)
        if front_text is not None:
            loaded_dict_data = json.loads(front_text)
            msg =  loaded_dict_data.get('message')
            user = self.scope['user']
            username = user.username if user.is_authenticated else 'default'
            notification_id = 'default'
            myResponse = {
                'message': msg,
                'username': username,
                'notification': notification_id,
            }
            print(myResponse)
            await self.create_chat_message(user, msg)
            await self.create_notification(user, msg)

            # broadcasts the message event to be sent, the group send layer
            # triggers the chat_message function for all of the group (chat_room)
            await self.channel_layer.group_send(
                self.chat_room,
                {
                    'type': 'chat_message',
                    'text': json.dumps(myResponse)
                }
            )

    # chat_method is a custom method name that we made
    async def chat_message(self, event):
        # sends the actual message
        await self.send({
                'type': 'websocket.send',
                'text': event['text']
        })

    async def websocket_disconnect(self, event):
        # when the socket disconnects
        print('disconnected', event)

    @database_sync_to_async
    def get_thread(self, user, other_username):
        return Thread.objects.get_or_new(user, other_username)[0]

    @database_sync_to_async
    def create_chat_message(self, me, msg):
        thread_obj = self.thread_obj
        return ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)

    @database_sync_to_async
    def create_notification(self, user, msg):
        last_chat = ChatMessage.objects.latest('id')
        created_notification = Notification.objects.create(notification_user=user, notification_chat=last_chat)
        print(created_notification)
        return created_notification
navbar.html

  <div id="notificationsBody" class="notifications">
              {% for notifications in notification|slice:"0:10" %}
              <a href="{% url 'chat:thread' user %}">
                <span id="notification-{{notification.id}}">
                  {{ notifications.notification_chat.message }}
                  via {{ notifications.notification_chat.user }}
                  at {{ notifications.notification_chat.timestamp }}
                </span>
              </a>
              {% endfor %}

{通知中通知的百分比|切片:“0:10”%}
{%endfor%}

要创建的
通知
对象,需要将
通知.通知用户
设置为
其他用户
。通知针对的是其他用户,而不是发送消息的用户

other_username = self.scope['url_route']['kwargs']['username']
other_user = User.objects.get(username=other_username)
await self.create_notification(other_user, msg)  #other_user, not the current user

但是,当将
通知更新为已读时,需要当前用户。

Hi!,不回答,但需要任何方式
Notification.objects.filter(Notification\u user=user)
-->
Notification.objects.filter(Notification\u user=user).update(Notification\u read=True)
,不需要
Notification.Notification\u read=True
Notification.save()
@BearBrownСПаабб:)很高兴听到这个消息,真的很酷!:)好的,当您说当更新通知为read时,当前用户是必需的,那么在
通知
模型中,当前用户在哪里使用?它只有与
其他用户关联的
通知用户
字段
对吗?同时更改为
其他用户
会出现错误
无法分配“'james'”:“通知。通知用户”必须是“用户”实例。
但是
james
是一个用户实例,这是因为我将james作为字符串传递,我假设我在
other\u user
下面添加了一行,就像这样
other\u user=user.objects.get(username=other\u user)
是的..你需要
user
实例。假设您有两个用户,
A
B
A
发送一条消息,那么
Notification
对象将用户设为
B
。因此,当
B
读取通知并且其客户端将消息发送到服务器时,当前用户是
B
,因此将有
notification
实例使用
Foreignkey
发送到
B