如何使用 django 通道和 websockets 从服务器的任何位置向客户端发送事件

How to send event to client from any place of server using django channels and websockets

现在我正在使用 django 和 angular 构建一个网站,我想在客户端和服务器之间添加 websocket 通信。 我按照 django 频道文档的说明进行操作。( https://channels.readthedocs.io/ ) 我想从 django 服务器代码的任何地方发送任何事件。但是当多个用户通过套接字连接时,服务器发送的数据总是发送给最后一个连接的用户。 这就是我所做的。 首先在 consumers.py 中,我如下定义了 ChatConsumer class 并添加了一个名为“tweet_send”的新处理程序函数

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name

        # Join room group
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()
    ...

    # here's what I added a new tweet send handler
    async def tweet_send(self, event):
        content = event['content']
        content["group_name"] = self.room_group_name

        # Send message to WebSocket
        await self.send(text_data=json.dumps({
            "type": "MESSAGE",
            "data": content
        }))

在 django 服务器端的某个地方(在 serializers.py 中),当创建新的推文时,我使用 django.channel_layer

向所有用户发送新的推文数据
...
def create(self, validated_data):
    ...
    new_tweet.save()

    # send message via channels
    channel_layer = get_channel_layer()
    all_users = list(Member.objects.filter(is_active = True).values_list('id', flat = True))
    for user_id in all_users:
        async_to_sync(channel_layer.group_send)(
            "chat_{}".format(user_id),            # this is the group name of group name of individual users.
            { "type": "chat_message", "message": "tweet created" }
        )

并且在 Angular websocket 服务中

init(userID: number): void{
  if(this.ws){
    this.ws.close();
  }

  this.ws = new WebSocket(`${environment.WEBSOCKET_URL}/chat/${userID}/`);
  this.ws.onopen = () => {
    this.currentWebSocketSubject.subscribe(data => {
      if (data) {
        this.ws?.send(JSON.stringify(data));
      }
    });
  };

  this.ws.onmessage = (event) => {
    console.log("message arrived");
    console.log(event);
    if (event.data) {
      const tempData: WS = JSON.parse(event.data) as WS;
      switch (tempData.type) {
        case 'MESSAGE':
          console.log("message arrived");
          console.log(tempData);
          if (tempData.data) {
            this.unreadMessages++;
            this.messageSubject.next(tempData);
          }
          break;

      }
    }
  };
}

我测试这些代码的时候,用了两个客户端,两个客户端登录,通过websockets成功连接到django服务器。 当我创建推文时,django 服务器使用 channel_layer.group_send 函数向每个频道发送事件,而在 ChatConsumer class 中添加的“tweet_send”函数将事件发送给用户。 这些事件分别针对不同的用户。 但是它们都被发送给最后一个连接到 websocket 的用户。 我不知道为什么。请帮助我。

我想你一定是在使用 channels 3.0.0 并且出现了这个错误。我建议您将频道版本升级到 3.0.1 或 3.0.2。 然后错误就会消失。