基于Django开发WhatsApp网页克隆版时WebSocket连接失败求助
WebSocket连接失败(404 Not Found)问题排查与解决
开发类似WhatsApp网页版的聊天应用时,遇到WebSocket连接ws://127.0.0.1:8000/ws/2/失败的问题,控制台显示Not Found: /ws/2/,以下是针对性的解决步骤:
1. 完善ASGI应用的协议配置
你的asgi.py仅配置了WebSocket协议处理,缺少HTTP协议的路由指向,导致Django无法正确处理HTTP请求,同时WebSocket路由也无法被正常识别。修改asgi.py:
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from .consumers import PersonalChatConsumer os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名.settings') application = ProtocolTypeRouter({ "http": get_asgi_application(), # 必须添加HTTP协议处理 "websocket": AuthMiddlewareStack( URLRouter([ path('ws/<int:id>/', PersonalChatConsumer.as_asgi()), ]) ), })
注意:Consumer必须调用.as_asgi()方法才能被ASGI正确实例化
2. 补充Consumer的连接接受逻辑
当前PersonalChatConsumer的connect方法仅完成了群组添加,未发送接受连接的指令,导致连接无法建立。修改consumers.py:
class PersonalChatConsumer(AsyncWebsocketConsumer): async def connect(self): my_id = self.scope['user'].id other_user_id = self.scope['url_route']['kwargs']['id'] if int(my_id) > int(other_user_id): self.room_name = f'{my_id}-{other_user_id}' else: self.room_name = f'{other_user_id}-{my_id}' self.room_group_name = 'chat_%s' % self.room_name await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() # 添加此行,接受WebSocket连接请求
3. 验证JavaScript中ID的正确性
检查document.getElementById('json-username').textContent返回的内容是否为数字类型的用户ID:
- 如果该元素存储的是用户名,需替换为存储用户ID的元素(比如
json-user-id),否则连接URL会变成/ws/用户名/,与路由的<int:id>规则不匹配,触发404错误。 - 可以在控制台打印
id值确认:console.log(id),确保是整数。
4. (可选)优化路由结构(推荐)
将WebSocket路由单独拆分到routing.py文件,提升代码可维护性:
创建项目根目录下的routing.py:
from django.urls import path from .consumers import PersonalChatConsumer websocket_urlpatterns = [ path('ws/<int:id>/', PersonalChatConsumer.as_asgi()), ]
然后修改asgi.py:
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from .routing import websocket_urlpatterns os.environ.setdefault('DJANGO_SETTINGS_MODULE', '你的项目名.settings') application = ProtocolTypeRouter({ "http": get_asgi_application(), "websocket": AuthMiddlewareStack( URLRouter(websocket_urlpatterns) ), })
内容的提问来源于stack exchange,提问作者KipronoKirui
相关产品推荐
相关产品推荐

