将消息发送到Django Channels 2中的组 [英] Sending messages to groups in Django Channels 2

查看:69
本文介绍了将消息发送到Django Channels 2中的组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我完全陷入困境,因为我无法让群组消息与Channels 2一起使用!我已经遵循了所有可以找到的教程和文档,但遗憾的是,我还没有发现问题所在。我现在想做的是有一个特定的URL,该URL在被访问时应该向名为事件的组广播一条简单的消息。



首先,这里是我在Django中使用的相关设置和当前设置:

  CHANNEL_LAYERS = {
'default':{
'BACKEND':'channels_redis.core.RedisChannelLayer',
'CONFIG':{
'hosts':[('localhost',6379)],
},
}
}

ASGI_APPLICATION ='backend.routing.application'

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
' django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'channels',
'channels_redis',
'backend.api'
]

接下来,这是我的EventConsumer,扩展了JsonWebsocketConsumer以非常基本的方式。这一切都是在收到消息时回显,这是可行的!因此,简单的send_json响应会按预期到达,只有组广播无效。

 类EventConsumer(JsonWebsocketConsumer) :
groups = [ events]

def connect(self):
self.accept()

def connect(self,close_code) :
print(关闭的Websocket,代码:,close_code)
self.close()

def receive_json(self,content,** kwargs):
print(接收到的事件:{} \nFrom:{} \nGroups:
{}。format(content,
self.channel_layer,
self.groups))

self.send_json(内容)

def event_notification(self,event):
self.send_json(
{
'type':'test ',
'内容':事件
}

和以下是我要触发广播的URL的URL配置:



项目urls.py

 从backend.events将URL导入为event_urls 

urlpatterns = [
url(r'^ events /',include(event_urls))
]

事件应用urls.py

 来自backend.events.views导入警报

urlpatterns = [
url(r'alarm',警报)
]

最后,视图本身应该在组广播的位置进行:



从django.shortcuts导入HttpResponse
从channel.layers导入get_channel_layer
从asgiref.sync导入async_to_sync


def警报(req):
layer = get_channel_layer()
async_to_sync(layer.group_send)('events',{'type':'test'})
return HttpResponse('< ; p> Done< / p>')


解决方案

I找到了解决方案在写这个问题时以为其他人也可以利用它!由于此处的大多数问题都与2.0或更高版本之前的频道版本有关,因此这就是您应如何处理使用者中的group_send事件。



问题不仅仅在于我如何使用 group_send 函数,我还错误地认为添加了我的EventConsumer的groups类变量应该自动将其添加到该/那些组中,但事实并非如此!您必须在 connect 类函数中手动添加组,并在 disconnect 函数中删除组!



然后,该问题还在于我的使用者没有指定适当的事件处理程序。在查看警报请求的视图文件中,我已将类型设置为测试。测试未反映在我的EventConsumer类中,因此无法处理该事件。如多聊天示例中所述,在线此处数字146,将根据发送事件的类型来调用帮助程序函数。因此,事件类型 event.alarm在您的使用者中应具有相应的 event_alarm 功能!很简单,但是记录的不是很好:)。最终的解决方案如下:



consumers.py 中,注意 group_add 处于连接状态, group_discard 处于断开状态!

  class EventConsumer(JsonWebsocketConsumer):

def connect(self):
async_to_sync(self.channel_layer.group_add)(
'events',
self。 channel_name

self.accept()

def connect(self,close_code):
print(已关闭的Websocket,代码为,close_code)
async_to_sync(self.channel_layer.group_discard)(
'events',
self.channel_name

self.close()

def receive_json( self,content,** kwargs):
print( Received event:{}。format(content))
self.send_json(content)

#--- -------------------------------------------------- ------------------------------------------------ -------------
#处理程序定义!处理程序将接受其相应的消息类型。类型为event.alarm
#的消息必须具有功能event_alarm
#--------------------------- -------------------------------------------------- -------------------------------------

def events_alarm(self,事件):
self.send_json(
{
'type':'events.alarm',
'content':event ['content']
}

因此,上述函数 events_alarm 从以下 group_send 调用:

 从django.shortcuts从channel.layers导入HttpResponse 

从asgiref.sync导入get_channel_layer

导入async_to_sync


def警报(req):
layer = get_channel_layer()
async_to_sync(layer.group_send)('events',{
'type':'events.alarm',
'content':'触发'
})
返回HttpResponse('< p> Done< / p&g t;’)

如果您需要进一步说明问题/答案,请告诉我!干杯!


I am completely stuck in that I cannot get group messaging to work with Channels 2! I have followed all tutorials and docs that I could find, but alas I haven't found what the issue seems to be yet. What I am trying to do right now is to have one specific URL that when visited should broadcast a simple message to a group named "events".

First things first, here are the relevant and current settings that I employ in Django:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('localhost', 6379)],
        },
    }
}

ASGI_APPLICATION = 'backend.routing.application'

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'corsheaders',
    'channels',
    'channels_redis',
    'backend.api'
]

Next, here is my EventConsumer, extending the JsonWebsocketConsumer in a very basic way. All this does is echo back when receiving a message, which works! So, the simple send_json response arrives as it should, it is ONLY group broadcasting that does not work.

class EventConsumer(JsonWebsocketConsumer):
    groups = ["events"]

    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        print("Closed websocket with code: ", close_code)
        self.close()

    def receive_json(self, content, **kwargs):
        print("Received event: {}\nFrom: {}\nGroups: 
                               {}".format(content, 
                                          self.channel_layer, 
                                          self.groups))

        self.send_json(content)

    def event_notification(self, event):
        self.send_json(
            {
                'type': 'test',
                'content': event
            }
        )

And here is the URL configurations for the URL that I want to trigger the broadcast:

Project urls.py

from backend.events import urls as event_urls

urlpatterns = [
    url(r'^events/', include(event_urls))
]

Events app urls.py

from backend.events.views import alarm

urlpatterns = [
    url(r'alarm', alarm)
]

And finally, the view itself where the group broadcast should take place:

from django.shortcuts import HttpResponse
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync


def alarm(req):
    layer = get_channel_layer()
    async_to_sync(layer.group_send)('events', {'type': 'test'})
    return HttpResponse('<p>Done</p>')

解决方案

I found the solution while writing this questions and thought that someone else might also make use of it! Since most of the questions out here are about channels version prior to 2.0 and above, this is how you should handle group_send events in your consumers.

The problem did not only lie in how I used the group_send function though, I had wrongly assumed that adding the groups class variable to my EventConsumer should automatically add it to that/those groups, it does NOT! You have to add groups manually in the connect class function and remove groups in the disconnect function!

The problem then also lied in that my consumer did not have proper event handlers specified. In my view file, where the alarm request is taken in, I had set the 'type' to 'test'. Test was not reflected in my EventConsumer class so the event could not be processed. As noted in the multichat example here on line number 146, the helper functions get called depending on the type of the event sent. So an event type of 'event.alarm' should have a corresponding function of event_alarm in your consumer! Simple, but not so well documented :). Here is what the final solution looked like:

In consumers.py, note the group_add in connect and the group_discard in disconnect!

class EventConsumer(JsonWebsocketConsumer):

    def connect(self):
        async_to_sync(self.channel_layer.group_add)(
            'events',
            self.channel_name
        )
        self.accept()

    def disconnect(self, close_code):
        print("Closed websocket with code: ", close_code)
        async_to_sync(self.channel_layer.group_discard)(
            'events',
            self.channel_name
        )
        self.close()

    def receive_json(self, content, **kwargs):
        print("Received event: {}".format(content))
        self.send_json(content)

    # ------------------------------------------------------------------------------------------------------------------
    # Handler definitions! handlers will accept their corresponding message types. A message with type event.alarm
    # has to have a function event_alarm
    # ------------------------------------------------------------------------------------------------------------------

    def events_alarm(self, event):
        self.send_json(
            {
                'type': 'events.alarm',
                'content': event['content']
            }
        )

So, the above function events_alarm gets called from the following group_send:

from django.shortcuts import HttpResponse

from channels.layers import get_channel_layer

from asgiref.sync import async_to_sync


def alarm(req):
    layer = get_channel_layer()
    async_to_sync(layer.group_send)('events', {
        'type': 'events.alarm',
        'content': 'triggered'
    })
    return HttpResponse('<p>Done</p>')

Please let me know if you need any more clarifications to the question/answer! Cheers!

这篇关于将消息发送到Django Channels 2中的组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆