一、搭建 WebSocket Django 应用
(一)准备工作
-
安装必要的依赖
- 首先需要安装
Django
和Channels
。Django Channels
扩展库让 Django 支持 WebSocket 和其他异步协议。
pip install django channels
- 首先需要安装
-
创建 Django 项目和应用
- 使用
django-admin
创建一个新的 Django 项目和一个应用。
django-admin startproject myproject cd myproject python manage.py startapp chat
- 使用
-
安装 ASGI 服务器
- 由于 WebSocket 是基于异步的协议,Django 默认是基于 WSGI 的(即同步的),因此需要使用 ASGI 服务器来支持异步协议。
- 安装
daphne
,它是 Django Channels 推荐的 ASGI 服务器。
pip install daphne
(二)配置 Django Channels
-
修改
settings.py
- 在
INSTALLED_APPS
中添加channels
和chat
应用。 - 配置
ASGI_APPLICATION
为myproject.asgi.application
,指向 ASGI 配置文件。
INSTALLED_APPS = [...'channels','chat', ]ASGI_APPLICATION = 'myproject.asgi.application'
- 在
-
创建
asgi.py
配置文件- 在项目根目录下(与
settings.py
同级)创建asgi.py
文件,并配置 Channels 路由。
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from chat import routingos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')application = ProtocolTypeRouter({"http": get_asgi_application(),"websocket": AuthMiddlewareStack(URLRouter(routing.websocket_urlpatterns)), })
- 在项目根目录下(与
(三)配置 WebSocket 路由
-
创建
routing.py
- 在
chat
应用目录下创建routing.py
文件,用于配置 WebSocket 路由。
from django.urls import re_path from . import consumerswebsocket_urlpatterns = [re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()), ]
- 在
(四)编写 WebSocket 消费者
-
创建消费者(Consumer)
- 消费者是 WebSocket 的核心,它负责接收来自客户端的消息、处理消息和发送消息回客户端。
- 在
chat
应用中创建consumers.py
文件,并定义一个简单的消费者类ChatConsumer
。
import json from channels.generic.websocket import AsyncWebsocketConsumerclass ChatConsumer(AsyncWebsocketConsumer):async def connect(self):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)# 接收来自 WebSocket 的消息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})# 接收房间组的消息async def chat_message(self, event):message = event['message']# 发送消息到 WebSocketawait self.send(text_data=json.dumps({'message': message}))
(五)配置 Channel Layer
-
安装 Redis
- Channels 默认使用 Redis 作为消息传递系统,因此需要安装 Redis。
pip install channels_redis
-
修改
settings.py
配置 Channel Layer- 在
settings.py
中配置 Channel Layer,指定 Redis 作为消息传递中介。可以使用默认内存
CHANNEL_LAYERS = {'default': {'BACKEND': 'channels_redis.core.RedisChannelLayer',# "BACKEND": "channels.layers.InMemoryChannelLayer", # 开发环境使用内存层'CONFIG': {"hosts": [('127.0.0.1', 6379)],},}, }
- 在
(六)创建前端界面(window.location.host可以改成后端服务地址)
-
前端 HTML 文件
- 在
chat
应用的templates
文件夹下创建一个chat_room.html
文件,用于显示聊天界面并连接 WebSocket。
<!DOCTYPE html> <html> <head><title>Chat Room</title> </head> <body><h2>Chat Room: {{ room_name }}</h2><div id="chat-log"></div><input id="chat-message-input" type="text" size="100"><button id="chat-message-input-btn">Send</button><script>const roomName = "{{ room_name }}";const chatSocket = new WebSocket('ws://' + window.location.host + '/ws/chat/' + roomName + '/');chatSocket.onmessage = function(e) {const data = JSON.parse(e.data);document.querySelector('#chat-log').innerHTML += '<br>' + data.message;};chatSocket.onclose = function(e) {console.error('Chat socket closed unexpectedly');};document.querySelector('#chat-message-input-btn').onclick = function(e) {const messageInputDom = document.querySelector('#chat-message-input');const message = messageInputDom.value;chatSocket.send(JSON.stringify({'message': message}));messageInputDom.value = '';};</script> </body> </html>
- 在
-
在视图中渲染 HTML
- 在
views.py
中添加视图,以渲染聊天页面。
from django.shortcuts import renderdef room(request, room_name):return render(request, 'chat/chat_room.html', {'room_name': room_name})
- 在
-
配置 URL 路由
- 在
urls.py
中添加 URL 配置。
from django.urls import path from . import viewsurlpatterns = [path('chat/<str:room_name>/', views.room, name='room'), ]
- 在
(七)运行应用
-
启动 Redis 服务如果没用Redis可以不用运行启动
- 启动 Redis 服务器(确保已安装 Redis)。
redis-server
-
运行 Django 服务器
- 最后,使用 Daphne 启动 Django 服务。
python manage.py runserver
(八)测试
-
访问应用
- 在浏览器中访问
http://127.0.0.1:8000/chat/room_name/
,room_name
是聊天房间的名称,多个用户可以同时访问相同的聊天房间,并通过 WebSocket 进行通信。
- 在浏览器中访问
二、总结
通过以上步骤,您已经从零开始搭建了一个支持 WebSocket 的 Django 应用。关键点是安装和配置 Channels
、使用 ASGI
替代 WSGI
来支持异步操作,并通过 Redis 实现多客户端的实时消息推送。
源码
已在github开源
Django封装高复用高可移植的apps系列