Django Channels+Redis开发聊天应用遇AsyncConsumer参数缺失错误求助
解决Django Channels中
AsyncConsumer.__call__() missing 1 required positional argument: 'send'错误 核心问题定位
这个错误的直接原因是ASGI路由中未用as_asgi()方法包装Consumer类。Channels 3.0+版本要求将Consumer类转换为ASGI可调用对象,否则会触发参数不匹配的异常。此外你的代码还有两处细节错误需要修正:
分步修复方案
1. 修正ASGI路由配置
在asgi.py的WebSocket路由中,必须用as_asgi()包装Consumer类:
- 原错误代码:
ws_patterns = [ path('ws/test/',TestConsumer) ] - 修改后:
ws_patterns = [ path('ws/test/',TestConsumer.as_asgi()) ]
同时建议把HTTP协议的ASGI应用也加入ProtocolTypeRouter,保证Django的HTTP请求正常处理:
application = ProtocolTypeRouter({ 'http': get_asgi_application(), 'websocket' : URLRouter(ws_patterns) })
2. 修复Consumer类的两处错误
- receive方法参数缺失:
WebsocketConsumer的receive方法必须接收text_data或bytes_data参数,否则会触发后续异常:def receive(self, text_data=None, bytes_data=None): # 可在此处添加消息处理逻辑 pass - group_add参数顺序颠倒:
channel_layer.group_add的第一个参数是组名,第二个是当前通道名,原代码顺序错误会导致无法正常加入组:async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name # 组名在前,通道名在后 )
另外建议在disconnect方法中添加离开组的逻辑,避免资源泄漏:
def disconnect(self, close_code): async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name )
完整修正后代码
asgi.py
""" ASGI config for chatapp project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/ """ import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter,URLRouter from django.urls import path from home.consumers import TestConsumer os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatapp.settings') application = ProtocolTypeRouter({ 'http': get_asgi_application(), 'websocket' : URLRouter([ path('ws/test/',TestConsumer.as_asgi()) ]) })
consumers.py
from channels.generic.websocket import WebsocketConsumer from asgiref.sync import async_to_sync import json class TestConsumer(WebsocketConsumer): def connect(self): self.room_group_name = "test_consumer_group" async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) self.accept() self.send(text_data=json.dumps({'status':'connected'})) def receive(self, text_data=None, bytes_data=None): # 这里可以添加消息处理逻辑,比如转发到组内 pass def disconnect(self, close_code): async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name )
内容的提问来源于stack exchange,提问作者Jaswanth Ch
相关产品推荐
相关产品推荐

