简体   繁体   English

整个网站上使用了一个Django Channels websocket使用者吗?

[英]One Django Channels websocket consumer used across whole site?

I have a Django project that uses WebSockets and one consumer ( ChatConsumer ) for both the chat and notification portion of the application. 我有一个使用WebSockets和一个使用者( ChatConsumer )进行应用程序的聊天和通知部分的Django项目。

I had routing.py set to url(r"^messages/(?P<username>[\\w.@+-]+)", ChatConsumer) however because notifications are also dependent on the websocket, they need to be accessed from any page on the site. 我将routing.py设置为url(r"^messages/(?P<username>[\\w.@+-]+)", ChatConsumer)但是由于通知也依赖于websocket,因此需要从以下位置访问它们网站上的任何页面。

The reason is that when a user clicks on the notification, it is marked as read using 原因是,当用户单击通知时,使用标记为已read

socket.send(JSON.stringify(data));

Right now notifications only work when a user is on the /messages/<username>/ URL. 现在,通知仅在用户位于/messages/<username>/ URL上时起作用。

If I change routing.py to account for the whole site, ( url(r"^", ChatConsumer) ), I obviously get a problem 如果我将routing.py更改为占整个站点( url(r"^", ChatConsumer) ),我显然会遇到问题

File "./consumers.py" in websocket_connect
    other_user = self.scope['url_route']['kwargs']['username']
  'username' 

Is there a simple way of resolving this? 有解决此问题的简单方法吗? Because correct me if I'm wrong but I don't think writing a new consumer is appropriate since the notifications and chat are deeply intertwined? 因为如果我错了就纠正我,但是由于通知和聊天紧密地纠缠在一起,所以我认为写一个新的使用者不合适吗?

consumers.py users.py

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

        other_user = self.scope['url_route']['kwargs']['username']
        me = self.scope['user']
        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')
        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).update(notification_read=True)
            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)
            other_user = self.scope['url_route']['kwargs']['username']
            other_user = User.objects.get(username=other_user)
            await self.create_notification(other_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, other_user, msg):
        last_chat = ChatMessage.objects.latest('id')
        created_notification = Notification.objects.create(notification_user=other_user, notification_chat=last_chat)
        return created_notification

base.html base.html

<script>
    $(document).ready(function() {
      // $('div[id^="notification-"]')
      $("#notificationLink").click(function() {
        $('span[id^="notification"]').each(function() {
          var username = '{{ request.user.username }}'
          var data = {
            "type": "notification_read",
            "username": username,
          }
          socket.send(JSON.stringify(data));
        });
    });
  </script>

<script>
...
    var endpoint = wsStart + loc.host + loc.pathname
    var socket = new ReconnectingWebSocket(endpoint)
    // all the websocket scripts - client side*
...
</script>

I think you should send other_user with message so it should be like that 我认为您应该向other_user发送消息,所以应该这样

 msg =  loaded_dict_data.get('message')
 other_user =  loaded_dict_data.get('other_user')

so you no more need to use self.scope['url_route']['kwargs']['username'] 因此您不再需要使用self.scope ['url_route'] ['kwargs'] ['username']
BTW can you share the code on github because i prepare to do something like this and i think your project will help me alot 顺便说一句,您能在github上共享代码吗,因为我准备做这样的事情,并且我认为您的项目会对我有很大帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Django 通道 WebSocket 参数 - Django Channels WebSocket argument Django 通道使用安全的 WebSocket 连接 - WSS:// - Django channels using secured WebSocket connection - WSS:// Django 通道 websocket 不接收发送的数据 - Django channels websocket not receiving data sent Django Channels - 拒绝未经授权的 websocket 请求的正确方法? - Django Channels - correct way to reject an unauthorized websocket request? 创建一个站点中使用的所有图像的数组 - Create an array of all images used across a site 整个网站的setTimeout,而不仅仅是一页 - setTimeout for whole site, not just one page Django 通道失败:WebSocket 握手期间出错:net::ERR_CONNECTION_RESET - Django Channels failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET 将授权凭证发送到Django通道WebSocket(无需将令牌设置为cookie) - Send Authorization Credentials to Django-channels WebSocket (without setting token as cookie) django 通道自定义令牌已验证 Websocket 不断断开连接 ERR_CONNECTION_RESET - django channels custom token authenticated Websocket keeps disconnecting ERR_CONNECTION_RESET 通过 Websocket 连接将文件上传到 Django 频道(来自本机应用程序) - Upload files to Django Channels through a Websocket connection ( from react native app )
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM