You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Channels ChatConsumer.disconnect()参数不匹配TypeError排查

Django Channels WebSocket断开连接报错排查

问题背景

使用Django Channels开发WebSocket聊天应用,参照视频教程完成代码编写后运行持续报错,自行检索尝试多种解决方案未修复。

相关代码

consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
# from asgiref.sync import sync_to_async

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name ='chat_%s' % self.room_name

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name,
        )

        await self.accept()

    async def disconnect(self):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name,
        )

routing.py

from django.urls import path
from room import consumers

websocket_urlpatterns=[
    path('ws/<str:room_name>/',consumers.ChatConsumer.as_asgi()),
]

asgi.py

import os

from django.core.asgi import get_asgi_application

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

import room.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangochat.settings')

application = ProtocolTypeRouter({
    "http":get_asgi_application(),
    "websocket":AuthMiddlewareStack(
        URLRouter(
            room.routing.websocket_urlpatterns
        )
    )
})

报错信息

Exception inside application: ChatConsumer.disconnect() takes 1 positional argument but 2 were given
Traceback (most recent call last):
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\staticfiles.py", line 44, in __call__
    return await self.application(scope, receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\routing.py", line 71, in __call__
    return await application(scope, receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\sessions.py", line 263, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\auth.py", line 185, in __call__
    return await super().__call__(scope, receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\middleware.py", line 26, in __call__
    return await self.inner(scope, receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\routing.py", line 150, in __call__
    return await application(
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\utils.py", line 51, in await_many_dispatch
    await dispatch(result)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\consumer.py", line 73, in dispatch
    await handler(message)
  File "C:\Users\dines\Desktop\trying_again\venv\lib\site-packages\channels\generic\websocket.py", line 238, in websocket_disconnect
    await self.disconnect(message["code"])
TypeError: ChatConsumer.disconnect() takes 1 positional argument but 2 were given

报错原因

Django Channels的AsyncWebsocketConsumer类中,disconnect方法被框架调用时会自动传入WebSocket关闭状态码参数,你当前定义的disconnect方法仅声明了self一个参数,无法接收框架传入的状态码,因此触发参数数量不匹配的类型错误。

注:多数旧教程编写时使用的是更早版本的Channels,部分旧版本disconnect方法不需要额外传code参数,版本迭代后接口规范发生了变化,这也是跟着旧教程写代码容易踩这个坑的原因。

修复方案

修改consumers.py中的disconnect方法定义,补充接收状态码的参数即可,不需要在方法内部使用该参数也必须预留参数位置:

async def disconnect(self, code):
    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name,
    )

如果不需要用到关闭状态码,也可以将参数名写为下划线_表示忽略该参数,效果完全一致:

async def disconnect(self, _):
    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name,
    )

修改完成后重启Django服务即可解决该报错,开发时需要注意两个规范点:

  • 继承AsyncWebsocketConsumer实现自定义消费者时,三个核心生命周期方法的参数必须和框架要求保持一致:connect(self)、disconnect(self, code)、receive(self, text_data=None, bytes_data=None)
  • 参照教程开发时注意核对依赖版本,Channels 3.x及以上版本的disconnect方法都要求传入关闭状态码参数,2.x旧版本无此要求,版本不匹配是跟着旧教程写代码踩这类接口错误的核心原因。

内容的提问来源于stack exchange,提问作者Dinesh Babu Jalla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:34:03