【问题标题】:Python Django: Sending a message from server to client on database save()Python Django:在数据库保存()上从服务器向客户端发送消息
【发布时间】:2020-02-05 03:48:12
【问题描述】:

我想在保存模型时通知客户。 我首先在 post_save 上创建了一个 django-signal。

@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()。

【问题讨论】:

    标签: python django websocket django-channels django-signals


    【解决方案1】:

    这些步骤非常简单。您必须获取通道层并发送一条消息,并将 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 包装器,当您从同步范围调用异步代码时应该使用该包装器。

    【讨论】:

      猜你喜欢
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 2017-07-30
      • 1970-01-01
      • 2016-09-10
      相关资源
      最近更新 更多