Django Channels中async_to_sync(channel_layer.group_send())无法正常工作
Django Channels group_send 无法触发问题修复
先贴出你的消费者代码:
class AllEventConsumer(WebsocketConsumer): def connect(self): self.room_name = str(self.scope['url_route']['kwargs']['user_id']) self.room_group_name = 'all_event_'+self.room_name print('connect') print(self.room_group_name) async_to_sync(self.channel_layer.group_add( self.room_group_name, self.room_name )) async_to_sync(self.channel_layer.group_send( self.room_group_name , { 'type': 'update.list', 'value': 'Value' } )) self.accept() event = Synopsis_Event.give_all_events(self.room_name) self.send(text_data=json.dumps({ 'room_id': self.room_group_name, 'payload': event })) def update_list(self, event): print('inside update_list') print(event) data = json.loads(event['value']) self.send(text_data=json.dumps({ 'payload': data })) def disconnect(self, close_code): async_to_sync(self.channel_layer.group_discard)( self.room_name, self.room_group_name ) self.disconnect(close_code) def receive(self, text_data=None, bytes_data = None): print('DEF') print(type(json.loads(text_data))) async_to_sync(self.channel_layer.group_send)( self.room_group_name , { "type": "update.list", "value": text_data } )
问题排查与修复点:
group_add 参数顺序错误
group_add要求的第二个参数是当前消费者的channel名称,不是你的user_id。你应该用self.channel_name代替self.room_name,否则消费者根本没加入到指定组里,自然收不到组消息。
修复后:async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name )disconnect方法递归调用+参数错误
- 你在
disconnect里又调用了self.disconnect(close_code),会无限递归,直接删掉这行。 group_discard的参数顺序是(group_name, channel_name),你写反了,要调整:
async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name )- 你在
update_list里JSON解析错误
你在connect里发送的value是字符串'Value',不是JSON格式,json.loads('Value')会直接报错,导致update_list执行失败。要么把value改成合法JSON(比如'"Value"'),要么去掉json.loads直接用原始值:def update_list(self, event): print('inside update_list') print(event) # 如果value是纯字符串,直接用event['value'] data = event['value'] self.send(text_data=json.dumps({ 'payload': data }))外部调用group_send的注意点
如果要在消费者外部调用group_send,必须确保:- 使用正确的
async_to_sync包裹(同步代码里) - 组名称和消费者里的完全一致
- 消息的
type字段要和消费者里的方法名对应(比如update.list对应update_list方法,这个你是对的)
- 使用正确的
修复后的完整代码:
import json from channels.generic.websocket import WebsocketConsumer from asgiref.sync import async_to_sync from .models import Synopsis_Event # 确保导入正确 class AllEventConsumer(WebsocketConsumer): def connect(self): self.room_name = str(self.scope['url_route']['kwargs']['user_id']) self.room_group_name = 'all_event_'+self.room_name print('connect') print(self.room_group_name) # 修复group_add参数,用self.channel_name async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) # 修正value为合法JSON格式字符串 async_to_sync(self.channel_layer.group_send)( self.room_group_name, { 'type': 'update.list', 'value': json.dumps('Value') } ) self.accept() event = Synopsis_Event.give_all_events(self.room_name) self.send(text_data=json.dumps({ 'room_id': self.room_group_name, 'payload': event })) def update_list(self, event): print('inside update_list') print(event) # 正确解析JSON data = json.loads(event['value']) self.send(text_data=json.dumps({ 'payload': data })) def disconnect(self, close_code): # 修复group_discard参数顺序,去掉递归调用 async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name ) def receive(self, text_data=None, bytes_data=None): print('DEF') print(type(json.loads(text_data))) async_to_sync(self.channel_layer.group_send)( self.room_group_name, { "type": "update.list", "value": text_data } )
内容的提问来源于stack exchange,提问作者Kcube
相关产品推荐
相关产品推荐

