Соединение React и Django с настройкой канала - WebSocket-соединение не удалось
Я пытался настроить Django с каналами для предоставления уведомлений React.
https://github.com/axilaris/react-django-channels <-- Я поместил сюда код своего проекта.
в файле backend/backend/settings.py
INSTALLED_APPS = [
..
'channels',
]
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer'
}
}
ASGI_APPLICATION = 'backend.routing.application'
in backend/backend/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
#import backend.routing
import user_api.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": URLRouter(
user_api.routing.websocket_urlpatterns
#backend.routing.websocket_urlpatterns <-- not sure if should be this
),
})
в файле backend/user_api/routing.py
from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path
from . import consumers
application = ProtocolTypeRouter({
"websocket": URLRouter([
path("ws/notifications/", consumers.NotificationConsumer.as_asgi()),
]),
})
в файле backend/user_api/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class NotificationConsumer(AsyncWebsocketConsumer):
async def connect(self):
print "XXX connect"
await self.accept()
async def disconnect(self, close_code):
print "XXX disconnect"
pass
async def receive(self, text_data):
print "XXX receive"
text_data_json = json.loads(text_data)
message = text_data_json['message']
await self.send(text_data=json.dumps({
'message': message
}))
Наконец-то в React, App.js
useEffect(() => {
const ws = new WebSocket('ws://localhost:8000/ws/notification/');
ws.onopen = () => {
console.log('Connected to notification websocket');
};
ws.onmessage = e => {
const data = JSON.parse(e.data);
setMessage(data.message);
};
ws.onerror = e => {
console.error('WebSocket error', e);
};
ws.onclose = e => {
console.error('WebSocket closed', e);
};
return () => {
ws.close();
};
}, []);
Из журналов консоли браузера следует, что он не может подключиться
App.js:59 WebSocket connection to 'ws://localhost:8000/ws/notification/' failed:
App.js:71 WebSocket error Event
ws.onerror @ App.js:71
App.js:75 WebSocket closed CloseEvent
Обратите внимание, что React работает на порту 3000, а Django - на порту 8000
% npm start <-- React
% python manage.py runserver <-- Django
журналы от django и react https://gist.github.com/axilaris/2e0a5ae1887f7d12a226565efa85dd6f
журналы реакций
App.js:59 WebSocket connection to 'ws://localhost:8000/ws/notification/' failed:
App.js:71 WebSocket error Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
App.js:75 WebSocket closed CloseEvent {isTrusted: true, wasClean: false, code: 1006, reason: '', type: 'close', …}
Журналы django
WARNING:django.request:Not Found: /ws/notification/
Not Found: /ws/notification/
WARNING:django.request:Not Found: /ws/notification/
[27/Mar/2024 14:19:44] "GET /ws/notification/ HTTP/1.1" 404 2230
[27/Mar/2024 14:19:44,843] - Broken pipe from ('127.0.0.1', 60943)
[27/Mar/2024 14:19:44] "GET /ws/notification/ HTTP/1.1" 404 2230
[27/Mar/2024 14:19:44,843] - Broken pipe from ('127.0.0.1', 60947)
Мне кажется, что на стороне Django чего-то не хватает, что канал не настроен должным образом и не прослушивает соединение. Что я упускаю в своей настройке. Некоторые подозрения:
- channel не вызывается из-за того, что настройка канального сокета находится в user_api
- CORS
Проблема :-
Смотрите ниже.
application = ProtocolTypeRouter({
"websocket": URLRouter([
path("ws/notifications/", consumers.NotificationConsumer.as_asgi()),
]),
})
Это notifications
.
И
const ws = new WebSocket('ws://localhost:8000/ws/notification/');
Это notification
.
Путь должен быть таким же.
Используйте как показано ниже.
Ответ :-
application = ProtocolTypeRouter({
"websocket": URLRouter([
path("ws/notifications/", consumers.NotificationConsumer.as_asgi()),
]),
})
И
const ws = new WebSocket('ws://localhost:8000/ws/notifications/');
Информация :-
1)
Если вы настроили django-channels, то ваш консольный вывод при python manage.py runserver
должен быть примерно таким, как показано ниже.
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
August 19, 2022 - 10:20:28
Django version 4.1, using settings 'mysite.settings'
Starting ASGI/Daphne version 3.0.2 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Ищите Starting ASGI/Daphne version x.x.x
.
2) Daphne требуется на сервере разработки.
Как я понимаю, вам нужно переподключиться при ошибке. Приложение должно пытаться подключиться всегда, если оно еще не подключено.
Нравится это.
Function channels_connect(){
On_Connect{
Messages
}
On_error{
//reconnect here
channels_connect();
}
}
ASGI_APPLICATION должно ссылаться на ваше приложение asgi, правильно использовать этот путь:
ASGI_APPLICATION = "backend/backend/asgi.py"
для более точной настройки посмотрите документацию django channel Tutorial: