如何使用django-channels 2.0发送用户通知?

时间:2018-07-30 17:21:53

标签: django django-models django-views django-channels

我正在开发一个具有“房间”的聊天应用程序。每个房间有两个用户。一个用户可以在多个房间中,即一个用户有多个房间。现在他在一个房间里聊天。但是他在另一个房间里收到一条消息。我想将其他房间的消息通知给用户。我应该如何实现呢?

当前,Websocket连接已建立为:ws://localhost:8000/chat/int<room_id>/

并且group_name命名为"room"+room_id。到目前为止,我有:

async def connect(self):
    room_id = self.scope['url_route']['kwargs']['room_id']
    await self.channel_layer.group_add(
            "room"+room_id,
            self.channel_name
        )
    await self.accept()

async def receive(self, text_data):
    await self.channel_layer.group_send(
        self.room_name,
        {
            'type': 'chat_message',
            'message': json.loads(text_data)
        }
    )
async def chat_message(self, event):
    await self.send(text_data=json.dumps({
        'message': event['message']
    }))

Django 2.x django-channels 2.x python 3.6

3 个答案:

答案 0 :(得分:1)

您至少需要两个模型MessageMessageThread。当用户连接到套接字时,通道将添加到用户所在的每个线程组中。您还必须将channel_name添加到用户会话中。

messaging/models.py

class MessageThread(models.Model):
    title = models.CharField()
    clients = models.ManyToManyField(User, blank=True)

class Message(models.Model):
    date = models.DateField()
    text = models.CharField()
    thread = models.ForeignKey('messaging.MessageThread', on_delete=models.CASCADE)
    sender = models.ForeignKey(User, on_delete=models.SET_NULL)

chat/consumers.py

class ChatConsumer(WebSocketConsumer):
    def connect(self):
        if self.scope['user'].is_authenticated:
            self.accept()
            # add connection to existing groups
            for thread in MessageThread.objects.filter(clients=self.scope['user']).values('id'):
                async_to_sync(self.channel_layer.group_add)(thread.id, self.channel_name)
            # store client channel name in the user session
            self.scope['session']['channel_name'] = self.channel_name
            self.scope['session'].save()

    def disconnect(self, close_code):
        # remove channel name from session
        if self.scope['user'].is_authenticated:
            if 'channel_name' in self.scope['session']:
                del self.scope['session']['channel_name']
                self.scope['session'].save()
            async_to_sync(self.channel_layer.group_discard)(self.scope['user'].id, self.channel_name)

答案 1 :(得分:0)

我做类似的事情,您可以尝试这样的事情:

connect(message):
    // however you get your chatroom value from the socket
    Group("%s" % chatroom).add(message.reply_channel)

message(message):
    message = json.loads(message.content['text'])
    chatroom = message['chatroom']  
    Group("%s" % chatroom).send({
            "text": json.dumps({
                "id": "newuser",
                "username": message['username'],
                "message": message['message']
            })
        })

我可能误解了您的问题。也许更像是:

为每个用户创建一个唯一的ID,并将该值用作“聊天室”,然后向每条消息发送聊天室号码和应转到的用户号码。 Django可以解释用户ID并将消息发送到正确的频道,然后让Javascript解释消息和房间号以将其带到正确的页面?

这是一个有趣的主意

答案 2 :(得分:0)

(idea :)我打开了两个插座:

  1. 用户正在发短信的当前房间之一
  2. 第二个聊天室列表(也创建了一个隐藏的基本聊天室;更好的说:属于聊天室列表的通道层)

然后,在上面解释的第一个说明频道中,从任何用户收到的每条消息中,我都会向两个套接字发送适当的答复。

此处的示例:chatroom.subtionary.com(只需单击一个聊天室并输入电子邮件) 它还可以对聊天室列表进行重新排序并触发该元素,还可以在其元素下写入每个聊天室的最后一条消息,还可以享受回复和删除的功能!

(我知道这是最懒的方式,但是效果很好)