这里写自定义目录标题
-
- [**1. 配置 `asgi.py` 文件**](#1. 配置
asgi.py
文件) -
- [**`asgi.py` 配置**](#
asgi.py
配置)
- [**`asgi.py` 配置**](#
- [**2. 配置 WebSocket 路由**](#2. 配置 WebSocket 路由)
-
- [**`routing.py` 配置**](#
routing.py
配置)
- [**`routing.py` 配置**](#
- [**3. 配置 WebSocket 消费者**](#3. 配置 WebSocket 消费者)
-
- [**`consumers.py` 配置**](#
consumers.py
配置)
- [**`consumers.py` 配置**](#
- [**4. 配置普通 HTTP 视图**](#4. 配置普通 HTTP 视图)
-
- [**`views.py` 配置**](#
views.py
配置) - [**`urls.py` 配置**](#
urls.py
配置)
- [**`views.py` 配置**](#
- [**5. 配置 `settings.py` 文件**](#5. 配置
settings.py
文件) - [**6. 启动 Django 项目**](#6. 启动 Django 项目)
-
- [**方式 1:使用 Daphne 启动 ASGI 服务器**](#方式 1:使用 Daphne 启动 ASGI 服务器)
- [**方式 2:使用 Uvicorn 启动 ASGI 服务器**](#方式 2:使用 Uvicorn 启动 ASGI 服务器)
- [**方式 3:在 PyCharm 中配置运行**](#方式 3:在 PyCharm 中配置运行)
- [**7. 测试 WebSocket 和 HTTP 请求**](#7. 测试 WebSocket 和 HTTP 请求)
- **总结**
- [**1. 配置 `asgi.py` 文件**](#1. 配置
要在 Django 项目中同时支持 WebSocket 和 普通视图 (HTTP 请求)的访问,你需要正确配置 Django ASGI 和 WSGI 的路由,使得两者可以并行运行。Django Channels 会处理 WebSocket 连接,而传统的 HTTP 请求可以通过 Django 的视图处理。
以下是详细的配置步骤,让你在同一个 Django 项目中同时支持 WebSocket 和传统的 HTTP API 访问:
1. 配置 asgi.py
文件
在 asgi.py
中,你需要同时配置 HTTP 和 WebSocket 路由。ProtocolTypeRouter
会根据请求的类型来分发请求:
- HTTP 请求 :使用标准的 Django WSGI 应用处理(
get_asgi_application()
)。 - WebSocket 请求:通过 Channels 处理 WebSocket 连接。
asgi.py
配置
python
# your_project_name/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import your_app.routing # 引入 WebSocket 路由
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(), # 处理传统 HTTP 请求
"websocket": AuthMiddlewareStack( # 处理 WebSocket 请求
URLRouter(
your_app.routing.websocket_urlpatterns # 配置 WebSocket 路由
)
),
})
get_asgi_application()
负责处理所有的 HTTP 请求(GET、POST、PUT 等)。AuthMiddlewareStack
用于 WebSocket 的认证中间件(可以扩展用于 WebSocket 认证)。your_app.routing.websocket_urlpatterns
是你配置 WebSocket 路由的地方。
2. 配置 WebSocket 路由
在你的应用的 routing.py
文件中配置 WebSocket 路由:
routing.py
配置
python
# your_app/routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/test/', consumers.TestConsumer.as_asgi()), # WebSocket 路由
]
这里的 TestConsumer
是 WebSocket 消费者类,负责接收和处理 WebSocket 请求。
3. 配置 WebSocket 消费者
在 consumers.py
中,你定义了如何处理 WebSocket 连接。以下是一个简单的例子:
consumers.py
配置
python
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class TestConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = 'test_room'
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
}
)
async def chat_message(self, event):
message = event['message']
# 发送消息到 WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
- connect:处理 WebSocket 连接时的逻辑,加入一个房间。
- disconnect:处理断开连接时的逻辑。
- receive:接收来自客户端的消息,并广播给房间内的其他客户端。
- chat_message:当有消息需要广播时,发送到所有客户端。
4. 配置普通 HTTP 视图
你可以像正常的 Django 项目一样,使用视图来处理普通的 HTTP 请求。
views.py
配置
例如,创建一个简单的视图,返回 JSON 数据:
python
# your_app/views.py
from django.http import JsonResponse
def api_view(request):
return JsonResponse({'message': 'Hello, this is a regular HTTP API'})
urls.py
配置
在 urls.py
中配置 HTTP 路由:
python
# your_app/urls.py
from django.urls import path
from .views import api_view
urlpatterns = [
path('api/hello/', api_view), # 普通的 HTTP 接口
]
5. 配置 settings.py
文件
在 settings.py
文件中,确认配置了 ASGI_APPLICATION
,指向 asgi.py
文件:
python
# settings.py
ASGI_APPLICATION = 'your_project_name.asgi.application'
如果你打算使用 Redis 作为 WebSocket 的通道层,配置 CHANNEL_LAYERS
:
python
# settings.py
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)], # Redis 服务器地址
},
},
}
如果不使用 Redis,可以改用 InMemoryChannelLayer:
python
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
},
}
6. 启动 Django 项目
方式 1:使用 Daphne 启动 ASGI 服务器
安装 Daphne:
bash
pip install daphne
然后通过 Daphne 启动 Django ASGI 应用:
bash
daphne your_project_name.asgi:application
方式 2:使用 Uvicorn 启动 ASGI 服务器
安装 Uvicorn:
bash
pip install uvicorn
通过 Uvicorn 启动:
bash
uvicorn your_project_name.asgi:application --host 0.0.0.0 --port 8000
方式 3:在 PyCharm 中配置运行
你可以在 PyCharm 中创建一个 Django 配置,确保 ASGI_APPLICATION
配置正确,然后启动 ASGI 服务器。具体步骤如下:
- 打开 PyCharm,点击 Run > Edit Configurations。
- 点击 "+" ,选择 Django Server。
- 配置你的项目名称、主机和端口。
- 设置 Target 为
your_project_name.asgi:application
。 - 点击 Run 启动。
7. 测试 WebSocket 和 HTTP 请求
- WebSocket:可以在浏览器控制台或 Vue 前端应用中,使用 WebSocket 连接:
javascript
const socket = new WebSocket('ws://localhost:8000/ws/test/');
socket.onopen = function(event) {
console.log('WebSocket Connected');
socket.send(JSON.stringify({ 'message': 'Hello, WebSocket!' }));
};
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Received:', data.message);
};
socket.onclose = function(event) {
console.log('WebSocket Closed');
};
- HTTP 请求 :可以通过浏览器直接访问
http://localhost:8000/api/hello/
或通过 API 客户端进行调用,验证是否能正常访问传统的 HTTP 路由。
总结
通过配置 asgi.py
中的 ProtocolTypeRouter
,你可以在同一个 Django 项目中同时支持:
- 普通的 HTTP 视图 :通过
get_asgi_application()
处理。 - WebSocket 连接 :通过 Channels 的
URLRouter
和消费者进行处理。
这样,无论是 普通的 HTTP 请求 还是 实时的 WebSocket 连接,都可以并行工作,并且互不干扰。