Python Django:在保存数据时从服务器向客户端发送消息

5
我希望在我的模型保存后通知客户端。 我首先创建了一个 post_save 的 Django 信号。
@receiver(post_save, sender=Scooter)
async def scooter_post_update(sender, instance, created, **kwargs):
    # Notify client here

接下来,我基于django-channels创建了AsyncConsumer类,并提供了它的路由。

// routing.py
    application = ProtocolTypeRouter({
        # Empty for now (http->django views is added by default)
        'websocket': AllowedHostsOriginValidator(
            AuthMiddlewareStack(
                URLRouter(
                    [
                        path('scooters/', ScootersUpdateConsumer)
                    ]
               )
        )
    )
})

// consumers.py
    class ScootersUpdateConsumer(AsyncConsumer):
        async def websocket_connect(self, event):
            print("Connected!", event)
            await self.send({
                "type": "websocket.accept"
            })
        async def send_message(self):
            await self.send({
                "type": "websocket.send",
                'text': 'Oy, mate!'
            })
        async def websocket_receive(self, event):
            print("Receive!", event)
        async def websocket_disconnect(self, event):
            print("Disconnected!", event)

现在我的问题是,如何从scooter_post_update()方法中调用send_message()函数。
1个回答

3
步骤非常简单。您需要获取通道层,然后发送一条带有type键的消息,该键设置为您要监听的方法名称:
    import channels
    from asgiref.sync import async_to_sync

    @receiver(post_save, sender=Scooter)
    def scooter_post_update(sender, instance, created, **kwargs):
        channel_layer = channels.layers.get_channel_layer()
        async_to_sync(channel_layer.send)(
            {"type": "send_message", "data": data}
        )

请注意,您通过通道传递的所有数据必须是可序列化的,因此您必须事先确保所有对象都已序列化。

您传递给send方法的字典的强制部分是type键(如前所述),其中必须包含将在消费者上调用的方法名称。

此外,您可以使用组,以便将消息广播到一组侦听器:

和其他你想要发送到通道的东西。

    import channels
    from asgiref.sync import async_to_sync

    @receiver(post_save, sender=Scooter)
    def scooter_post_update(sender, instance, created, **kwargs):
        channel_layer = channels.layers.get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            "group_name", {"type": "send_message", "data": data}
        )

在消费者方面:

    class ScootersUpdateConsumer(AsyncConsumer):
        async def websocket_connect(self, event):
            await self.channel_layer.group_add("group_name", self.channel_name)
            await self.send({
                "type": "websocket.accept"
            })

请注意,在这两种情况下,您都需要使用 async_to_sync 包装器,该包装器应在您从同步范围调用异步代码时使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接