从消费者的外部听django渠道channel_layer

时间:2018-03-12 13:27:22

标签: websocket redis listener django-channels

文档说明可以从消费者外部发布到渠道图层:https://channels.readthedocs.io/en/latest/topics/channel_layers.html#using-outside-of-consumers 我需要做相反的事情。我有一个相当复杂的python脚本,它从pubnub读取实时数据,处理它,并通过channel_layer上的组将它推送给消费者。这工作正常,但我需要消费者能够宣布他们在这个脚本中的存在,以便它可以推送他们的数据(它只在从pubnub获取新数据时才推送到通道层,这可能是每24小时一次)。

我决定通过让消费者发布信息来解决这个问题。'连接上的频道。我现在需要pubnub源脚本来收听这个频道。 我已经尝试将以下内容添加到脚本中,它不再抛出错误,但它实际上并没有响应消息。它成功加入了通道层,但是消息处理程序(receive_json)永远不会触发。

from channels.generic.websocket import JsonWebsocketConsumer


class channelConsumer(JsonWebsocketConsumer):

    def __init__(self):
        self.channel_name = 'source'
    def join(self):
        async_to_sync(channel_layer.group_add)('presence', self.channel_name)
    def receive_json(self, message):
        print("Presence Detected")
        # do some stuff

进一步在代码中:

global channel_layer
channel_layer = get_channel_layer()

global listener
listener = channelConsumer()
listener.join()

正如我所说,没有明确的错误,它似乎似乎没有触发receive_json。肯定有数据包被发布到'存在',所以问题肯定在下面的代码中。

1 个答案:

答案 0 :(得分:0)

为使消费者接收消息,需要将该消费者插入路由器。最常见的情况是使用URLRouter,消费者将在其中从连接(例如Web套接字)接收事件。

您可以使用ChannelNameRouter创建将在特定Chanel上侦听的使用者。例如,消费者可能是:

from channels.consumer import SyncConsumer
class ChannelConsumer(SyncConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def post_save(self, event):
        print("POSTSAVE", event)

然后在路由器定义上

from channels.routing import ProtocolTypeRouter, URLRouter,ChannelNameRouter
application = ProtocolTypeRouter({
    "websocket": TokenAuthMiddlewareStack(
        URLRouter([
            url(r"^.*$", RestConsumer),
        ]),
    ),
    "channel":ChannelNameRouter({
        "signals": ChannelConsumer,
    })

})

现在您可以向该消费者发送消息

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
async_to_sync(channel_layer.send)("signals", {"type": "post.save", "message":"Hello Consumer"})

专门针对您的情况,如果您希望有多个通道接收消息,则还需要将“信号”通道添加到要使用的组中。

请注意,如果您使用ChannelNameRouter,则需要启动将对其进行处理的工作器。

./manage.py runworker signals