Django Channels对接Angular前端时出现路由错误:找不到socket/order路径
问题:Django Channels与Angular前端对接时WebSocket路由匹配失败
首次使用Django Channels对接现有Angular前端,严格遵循官方文档编写代码后,WebSocket路由仍无法正常匹配,报错信息如下:
Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). January 10, 2023 - 15:34:50 Django version 4.1.3, using settings 'BrokerBackEnd.settings' Starting ASGI/Daphne version 4.0.0 development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. WebSocket HANDSHAKING /socket/order [127.0.0.1:63732] HTTP GET /orders/ 200 [0.07, 127.0.0.1:63731] Exception inside application: No route found for path 'socket/order'. Traceback (most recent call last): File "C:\Users\Neha\Documents\broker-back-end-py\env\lib\site-packages\django\contrib\staticfiles\handlers.py", line 101, in __call__ return await self.application(scope, receive, send) File "C:\Users\Neha\Documents\broker-back-end-py\env\lib\site-packages\channels\routing.py", line 62, in __call__ return await application(scope, receive, send) File "C:\Users\Neha\Documents\broker-back-end-py\env\lib\site-packages\channels\routing.py", line 134, in __call__ raise ValueError("No route found for path %r." % path) ValueError: No route found for path 'socket/order'. WebSocket DISCONNECT /socket/order [127.0.0.1:63732]
相关代码文件
settings.py
INSTALLED_APPS = [ 'daphne', 'channels', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'corsheaders', 'rest_framework', 'Orders' ] ASGI_APPLICATION = 'BrokerBackEnd.asgi.application'
asgi.py
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter import Orders.routing as route os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BrokerBackEnd.settings') application = ProtocolTypeRouter({ 'http': get_asgi_application(), 'websocket': URLRouter( route.websocket_urlpatterns ) })
consumer.py
class OrderConsumer(WebsocketConsumer): def connect(self): self.accept() def receive(self, text_data=None, bytes_data=None): self.send(text_data="Message = " + text_data) def disconnect(self, code): return super().disconnect(code)
routing.py(Orders应用下)
from django.urls import re_path from .consumer import OrderConsumer websocket_urlpatterns = [ re_path(r"socket/order/", OrderConsumer.as_asgi()) ]
Angular前端代码
import { catchError, map } from 'rxjs/operators'; import { Injectable } from "@angular/core"; import { EMPTY, Observable } from "rxjs"; import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; import { Order } from './order.model'; import { MatSnackBar } from '@angular/material/snack-bar'; @Injectable({ providedIn: 'root' }) export class OrderWebSocketService { myWebSocket: WebSocketSubject<Order> = webSocket('ws://localhost:8000/socket/order'); constructor(private snackBar: MatSnackBar) { } public connect(): Observable<Order> { return this.myWebSocket.asObservable().pipe( map((obj) => obj), catchError((error) => this.errorHandler(error)) ); } public close(): void { this.myWebSocket.complete(); } errorHandler(e: any): Observable<any> { this.showMessage('Something wrong happened with websocket!', true); return EMPTY; } showMessage(msg: string, isError: boolean = false): void { this.snackBar.open(msg, 'X', { duration: 3000, horizontalPosition: "right", verticalPosition: "top", panelClass: isError ? ['msg-error'] : ['msg-success'] }); } }
解决建议
1. 修正路由正则匹配规则
当前后端路由正则r"socket/order/"要求路径结尾必须带斜杠,但前端请求的是/socket/order(无结尾斜杠),导致匹配失败。修改routing.py的正则表达式,让它兼容带/不带斜杠的请求:
from django.urls import re_path from .consumer import OrderConsumer websocket_urlpatterns = [ re_path(r"^socket/order/?$", OrderConsumer.as_asgi()) ]
^:匹配路径开头/?:表示结尾的斜杠是可选的$:匹配路径结尾
2. 确认Consumer的导入是否完整
检查consumer.py是否正确导入了WebsocketConsumer,否则会导致路由无法正确关联到Consumer:
from channels.generic.websocket import WebsocketConsumer class OrderConsumer(WebsocketConsumer): def connect(self): self.accept() def receive(self, text_data=None, bytes_data=None): self.send(text_data="Message = " + text_data) def disconnect(self, code): return super().disconnect(code)
3. 验证应用名称与导入路径的大小写一致性
Python对路径和模块名称大小写敏感,确认Orders应用的目录名称、routing.py的位置与asgi.py中的导入语句import Orders.routing as route完全匹配,避免因大小写问题导致路由未正确加载。
4. 检查CORS配置(可选)
如果前端和后端存在跨域情况,确保settings.py中正确配置了CORS允许WebSocket连接:
CORS_ALLOWED_ORIGINS = [ "http://localhost:4200", # Angular默认端口 ] # 允许WebSocket的跨域请求 CORS_ALLOW_CREDENTIALS = True
内容的提问来源于stack exchange,提问作者Neha
相关产品推荐
相关产品推荐

