Django channels websocket ValueError: Не найден маршрут для пути 'ws//'
В настоящее время я пытаюсь сделать приложение для чата, используя учебник Django channel в качестве основы для проекта. В настоящее время у меня возникла проблема, при которой WebSocket отключается и происходит Handshaking. Я новичок в Django и WebSocket. chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
chat/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:room_name>/', views.room, name='room'),
]
mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('chat.urls')),
path('admin/', admin.site.urls),
path("auth/", include("django.contrib.auth.urls")),
]
chat/consumers.py
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from .models import Room, Message
class ChatConsumer(WebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(args, kwargs)
self.room_name = None
self.room_group_name = None
self.room = None
self.user = None
def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = self.room_name
self.room = Room.objects.get(name=self.room_name)
self.user = self.scope['user']
# connection has to be accepted
self.accept()
# join the room group
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name,
)
if self.user.is_authenticated:
# send the join event to the room
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'user_join',
'user': self.user.username,
}
)
self.room.online.add(self.user)
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name,
)
if self.user.is_authenticated:
# send the leave event to the room
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'user_leave',
'user': self.user.username,
}
)
self.room.online.remove(self.user)
def receive(self, text_data=None, bytes_data=None):
text_data_json = json.loads(text_data)
message = text_data_json['message']
if not self.user.is_authenticated:
return
# send chat message event to the room
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'chat_message',
'user': self.user.username,
'message': message,
}
)
Message.objects.create(user=self.user, room=self.room, content=message)
def chat_message(self, event):
self.send(text_data=json.dumps(event))
def user_join(self, event):
self.send(text_data=json.dumps(event))
def user_leave(self, event):
self.send(text_data=json.dumps(event))
mysite/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
chat/static/room.js
const roomName = JSON.parse(document.getElementById('roomName').textContent);
let chatLog = document.querySelector("#chatLog");
let chatMessageInput = document.querySelector("#chatMessageInput");
let chatMessageSend = document.querySelector("#chatMessageSend");
let onlineUsersSelector = document.querySelector("#onlineUsersSelector");
// adds a new option to 'onlineUsersSelector'
function onlineUsersSelectorAdd(value) {
if (document.querySelector("option[value='" + value + "']")) return;
let newOption = document.createElement("option");
newOption.value = value;
newOption.innerHTML = value;
onlineUsersSelector.appendChild(newOption);
}
// removes an option from 'onlineUsersSelector'
function onlineUsersSelectorRemove(value) {
let oldOption = document.querySelector("option[value='" + value + "']");
if (oldOption !== null) oldOption.remove();
}
// focus 'chatMessageInput' when user opens the page
chatMessageInput.focus();
// submit if the user presses the enter key
chatMessageInput.onkeyup = function(e) {
if (e.keyCode === 13) { // enter key
chatMessageSend.click();
}
};
// clear the 'chatMessageInput' and forward the message
chatMessageSend.onclick = function() {
if (chatMessageInput.value.length === 0) return;
chatSocket.send(JSON.stringify({
"message": chatMessageInput.value,
}));
chatMessageInput.value = "";
};
let chatSocket = null;
function connect() {
chatSocket = new WebSocket("ws://" + window.location.host + "/ws/" + roomName + "/");
chatSocket.onopen = function(e) {
console.log("Successfully connected to the WebSocket.");
}
chatSocket.onclose = function(e) {
console.log("WebSocket connection closed unexpectedly. Trying to reconnect in 2s...");
setTimeout(function() {
console.log("Reconnecting...");
connect();
}, 2000);
};
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
console.log(data);
switch (data.type) {
case "chat_message":
chatLog.value += data.user + ": " + data.message + "\n";
break;
case "user_join":
chatLog.value += data.user + " joined the room.\n";
onlineUsersSelectorAdd(data.user);
break;
case "user_leave":
chatLog.value += data.user + " left the room.\n";
onlineUsersSelectorRemove(data.user);
break;
default:
console.error("Unknown message type!");
break;
}
// scroll 'chatLog' to the bottom
chatLog.scrollTop = chatLog.scrollHeight;
};
chatSocket.onerror = function(err) {
console.log("WebSocket encountered an error: " + err.message);
console.log("Closing the socket.");
chatSocket.close();
}
}
connect();
Выданная ошибка:
WebSocket HANDSHAKING /ws// [127.0.0.1:62654]
Exception inside application: No route found for path 'ws//'.
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/staticfiles.py", line 44, in __call__
return await self.application(scope, receive, send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/routing.py", line 71, in __call__
return await application(scope, receive, send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/sessions.py", line 47, in __call__
return await self.inner(dict(scope, cookies=cookies), receive, send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/sessions.py", line 263, in __call__
return await self.inner(wrapper.scope, receive, wrapper.send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/auth.py", line 185, in __call__
return await super().__call__(scope, receive, send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/middleware.py", line 26, in __call__
return await self.inner(scope, receive, send)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/channels/routing.py", line 168, in __call__
raise ValueError("No route found for path %r." % path)
ValueError: No route found for path 'ws//'.
WebSocket DISCONNECT /ws// [127.0.0.1:62654]
Я почти уверен, что мне нужно изменить синтаксис websocket_urlpatterns в routing.py, но не уверен, как к этому подступиться. Буду признателен, если есть ссылка или место, которое я могу найти, поскольку я не смог ничего нагуглить.