我尝试使用通道设置 Django 来向 React 提供通知。
https://github.com/axilaris/react-django-channels<-- I have put my project code here.
在后端/后端/settings.py
INSTALLED_APPS = [
..
'channels',
]
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer'
}
}
ASGI_APPLICATION = 'backend.routing.application'
在后端/后端/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
),
})
在后端/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()),
]),
})
在后端/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 端缺少一些东西,通道没有正确设置并且没有监听连接。我的设置中缺少什么。 有人怀疑:
问题:-
看下面。
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/');