Skip to main content
 首页 » 编程设计

python Django : Sending a message from server to client on database save()

2024年11月01日37birdshome

我想在保存模型时通知客户。 我首先在 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()。

请您参考如下方法:

步骤非常简单。您必须获取 channel 层并发送一条消息,并将 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} 
        ) 

以及您要通过 channel 发送的任何其他内容。

请注意,您传递的所有数据必须是可序列化的,因此您必须注意所有对象都已预先序列化。

传递给 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 包装器,当您从同步范围调用异步代码时应该使用它。