django channels 更适合已用 django 且需认证、数据库联动的场景;纯 websockets 更轻量,适合简单广播。channels 需 asgi、注意 async/await 和 sync_to_async,websockets 需手动处理 orm。

用 Django Channels 还是纯 websockets?先看你的场景
如果你的项目已基于 Django,且需要用户认证、数据库联动(比如发消息存记录、读取未读数)、与 HTTP 视图共用中间件或 session,Channels 是更稳妥的选择;它不是“额外加 WebSocket”,而是把 WebSocket 当作 Django 的一种新协议来统一处理。但如果你只是跑一个轻量后台服务,转发传感器数据或做简单广播,websockets 库几行代码就能起服务,没路由、没 ASGI 层、不依赖 Django——反而更干净。
-
Channels要求你改用ASGI服务器(如daphne或uvicorn),不能用runserver原生支持 WebSocket - 认证逻辑得写在
connect方法里,self.scope["user"]只有配置了AuthMiddlewareStack才有效,漏配就始终是AnonymousUser -
websockets服务无法直接调用models.py,想查数据库得手动进事件循环用sync_to_async包一层,否则会阻塞整个连接
consumers.py 里最常写的三个方法:怎么写、为什么这么写
一个典型的 AsyncWebsocketConsumer 类里,connect、receive、disconnect 是骨架。但容易忽略的是:它们都必须是 async 方法,且不能在其中直接调用同步 ORM 操作。
-
connect:别只做await self.accept(),要在这里校验 token 或 session。例如从self.scope["query_string"]解出b64token,再用await sync_to_async(get_user_from_token)(token)—— 否则连接一建立就断开,日志里只显示WebSocket DISCONNECT,没有具体原因 -
receive:收到的text_data是字符串,不是 JSON 自动解析后的 dict。常见错误是直接data["type"]报TypeError,得先json.loads(text_data) -
disconnect:这里不能发await self.send(),协议已关闭;但可以安全地清理缓存、发信号、删 Redis key
广播消息时,channel_layer.group_send 和直接遍历连接的区别
用组(group)广播是 Channels 推荐方式,不是因为“更高级”,而是为了解耦和可扩展。直接维护 self.connections = set() 看似简单,但在多进程或多机器部署下立刻失效。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
-
channel_layer.group_add("chat_room_123", self.channel_name)必须在connect里调用,且需确保 group name 是合法字符串(不能含空格、斜杠等) -
group_send发送的是字典,key 必须含"type"字段(如"chat.message"),对应 consumer 里同名方法chat_message(self, event),名字错一个字母就静默丢弃 - 本地开发用
channels.layers.InMemoryChannelLayer没问题,但上线必须换 Redis 层,否则不同 worker 实例之间组消息完全不互通
前端连不上?先检查这三处 wss:// 相关配置
Django 开发时默认是 ws://,但浏览器在 HTTPS 页面里禁止降级连接 ws://,所以即使后端没配 TLS,前端也得用 wss:// 并配合反向代理处理加密终止。
- Nginx 配置里漏了
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade";,连接会在 101 切换协议时卡住,Chrome 控制台报net::ERR_CONNECTION_CLOSED - Django
ALLOWED_HOSTS必须包含域名(不能只写*),否则Channels在connect阶段就拒绝请求,返回 400 且无日志 - 前端
new WebSocket("wss://example.com/ws/chat/")的 path 必须和routing.py中re_path(r"^ws/chat/$", ChatConsumer.as_asgi())完全一致,尾部斜杠缺一不可
复杂点在于:WebSocket 连接一旦建立,后续所有业务逻辑都运行在异步上下文里,同步代码像定时器、文件读写、旧版数据库驱动,稍不注意就会让整个 consumer 卡死。这不是 Channels 的问题,是 Python 异步模型本身的约束——得习惯把“可能慢”的事,都明确标成 await。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










