Django Channels WebSocket握手报__call__()缺失send参数错误如何解决
问题排查与解决步骤
1. 修复Consumer注册语法错误
报错__call__() missing 1 required positional argument: 'send'的核心原因是ASGI路由中注册Consumer时没有调用.as_asgi()方法,Channels要求必须通过该方法将Consumer类转换为可调用的ASGI实例。
修改asgi.py中的ws_pattern部分:
ws_pattern = [ path('ws/play/<room_code>', GameRoom.as_asgi()) ]
2. 补全ProtocolTypeRouter的HTTP协议配置
当前的ProtocolTypeRouter仅配置了websocket协议,缺失HTTP协议的处理逻辑,会导致普通HTTP请求异常,修改application配置:
application= ProtocolTypeRouter( { 'http': get_asgi_application(), 'websocket': AuthMiddlewareStack(URLRouter( ws_pattern )) } )
3. 修正路由与请求路径不匹配问题
测试时请求的路径是ws://127.0.0.1:8000/ws/tictactoe/play/testroomcode,但路由中定义的路径是ws/play/<room_code>,二者前缀不一致,二选一修改即可:
- 修改测试请求路径为
ws://127.0.0.1:8000/ws/play/testroomcode - 修改路由匹配规则为
path('ws/tictactoe/play/<room_code>', GameRoom.as_asgi())
4. 修正Consumer中Channel Layer的方法名错误
代码中调用的groups_add/groups_discard/groups_send方法名多了多余的s,正确的方法名是group_add/group_discard/group_send,修改consumer.py对应代码:
# 连接时加入群组 async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) # 断开时移除群组 async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name ) # 发送群组消息 async_to_sync(self.channel_layer.group_send)( self.room_group_name,{ 'type' : 'run_game', 'payload': text_data } )
补充提示:你在
group_send中指定了消息类型为run_game,需要在GameRoom类中添加对应的处理方法,否则会触发消息处理异常,示例:def run_game(self, event): data = event['payload'] self.send(text_data=json.dumps(data))
5. 检查基础配置是否完善
确认settings.py中已完成Channels的基础配置:
INSTALLED_APPS列表中添加'channels'- 配置
ASGI_APPLICATION = 'advancesource.asgi.application' - 若使用Channel Layer,需配置对应的后端(如Redis),示例配置:
CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": { "hosts": [("127.0.0.1", 6379)], }, }, }
内容的提问来源于stack exchange,提问作者Abindent
相关产品推荐
相关产品推荐

