如何使用django通道和websockets从服务器的任何地方发送事件到客户端

ff29svar  于 2022-11-11  发布在  Go
关注(0)|答案(2)|浏览(210)

Now I'm building a website using django and angular, And I want to add websocket communication between client and server. I followed the instructions of django channel documentation.( https://channels.readthedocs.io/ ) I want to send any event from any place of django server code. But when multiple users connect via socket, the data sent from server always goes to the last connected user. And here's what I did. First in consumers.py, I defined my ChatConsumer class as follows and added a new handler named "tweet_send" function

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
        }))

中 的 每 一 个
And somewhere of django server side(in serializers.py), when a new tweet is created, I send a new tweet data to all users using 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 服务 器 。 当 我 创建 一 个 tweet 时 , django 服务 器 使用 channel _ layer . group _ send 函数 将 事件 发送 到 每个 通道 ,在 ChatConsumer 类 中 增加 了 " tweet _ send " 函数 , 将 事件 发送 给 用户 , 这些 事件 分别 针对 不同 的 用户 , 但 都 发送 给 最 后 的 websocket -我 不 知道 为什么 请 帮帮 我 。

izj3ouym

izj3ouym1#

我想你一定是用的频道3.0.0版才出现这个错误。我建议你把频道版本升级到3.0.1或3.0.2版。这样错误就会消失。

oiopk7p5

oiopk7p52#

我可以看到这个问题已经存在很长时间了。你的代码有一个问题,这个问题是你的消费者中的tweet发送处理程序(tweet_send)与你从serializers.py发送到群组的消息类型不匹配。
为了解决这个问题,你必须重命名你的tweet发送处理器方法,以匹配你要发送到群组的消息类型,在本例中是chat_message


# tweet send handler

async def chat_message(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
    }))

我希望这对你有帮助。

相关问题