在 Web 开发中,实时通信场景(如在线聊天、实时数据监控、协作工具等)越来越常见。传统的 HTTP 协议基于 “请求 - 响应” 模式,无法满足实时双向通信的需求。
WebSocket 是一种在单个 TCP 连接上提供全双工通信的网络协议,它打破了 HTTP 的单向请求限制,让服务器和客户端可以随时向对方发送数据。
Upgrade: websocket
字段的请求,申请升级WebSocket 协议101 Switching Protocols
响应,连接从 HTTP 切换为 WebSocket相比传统的 HTTP 轮询(Polling)或长轮询(Long Polling),WebSocket 具有明显优势:
要在 Django 中使用 WebSocket,需要依赖 ASGI(Asynchronous Server Gateway Interface)——Python 异步 Web 应用的标准接口。
参考资料:ASGI 项目文档
Uvicorn 是一款高性能的 ASGI 服务器,专为异步 Web 应用设计,是运行 Django 实时应用的理想选择。
# standard 是指包含WebSocket支持的完整版
pip install "uvicorn[standard]"
# 查看版本
uvicorn --version
Django 项目默认包含asgi.py
入口文件,通过 Uvicorn 启动。进入项目根目录(包含manage.py的目录),运行下面命令
# 开发环境(自动重载)
uvicorn mysite.asgi:application --reload
# 或指定地址和端口
uvicorn mysite.asgi:application --host 0.0.0.0 --port 8000 --reload
参考资料:uvicorn官方文档
Django 本身不直接支持 WebSocket,需要通过Channels扩展实现。Channels 为 Django 添加了异步处理能力,使其能处理 WebSocket、HTTP2 等协议。
Django Channels的核心组件
安装
pip install channels
pip install channels_redis
安装Redis(过程略)
配置Django项目的mysite\mysite\settings.py
INSTALLED_APPS = [
# ...其他应用
"channels", # 添加Channels
]
# 指定ASGI应用入口
ASGI_APPLICATION = "mysite.asgi.application"
# 配置Redis通道层
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": ["redis://127.0.0.1:6379/3"], # Redis地址
},
},
}
点击查看完整代码
配置Django项目的mysite\mysite\asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django_application = get_asgi_application()
# 延迟导入WebSocket路由(避免循环导入)
def get_websocket_application():
from myapp.websocket.routing import websocket_urlpatterns
return AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
# 协议路由:区分HTTP和WebSocket请求
application = ProtocolTypeRouter({
"http": django_application,
"websocket": get_websocket_application()
})
点击查看完整代码
消费者(Consumer)是处理 WebSocket 逻辑的核心,类似 Django 的视图,支持同步和异步两种模式。
消费者类型
AsyncWebsocketConsumer
:异步处理(推荐),适合高并发场景SyncWebsocketConsumer
:同步处理,适合简单逻辑或需集成同步代码JsonWebsocketConsumer
:专门处理 JSON 格式消息,自动解析 / 序列化异步消费者示例
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class ChatConsumer(AsyncWebsocketConsumer):
# 连接建立时调用
async def connect(self):
# 从URL获取房间名
self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
self.room_group_name = f"chat_{self.room_name}"
# 加入房间组
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
# 接受连接
await self.accept()
# 连接关闭时调用
async def disconnect(self, close_code):
# 离开房间组
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# 接收客户端消息
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
# 发送消息到房间组(广播给同组所有连接)
await self.channel_layer.group_send(
self.room_group_name,
{"type": "chat.message", "message": message}
)
# 处理房间组消息(方法名对应group_send中的type字段)
async def chat.message(self, event):
message = event["message"]
# 发送消息给客户端
await self.send(text_data=json.dumps({"message": message}))
通过路由将 WebSocket URL 映射到消费者,类似 Django 的 URL 配置
# routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r"ws/chat/(?P\w+)/$" , consumers.ChatConsumer.as_asgi()),
]
您正在阅读的是《Django从入门到实战》专栏!关注不迷路~