I’ved tried to setup Django with channels to provide notification to React.
https://github.com/axilaris/react-django-channels <– I have put my project code here.
in 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
),
})
in 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()),
]),
})
in 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
}))
Finally in 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();
};
}, []);
From the browser console logs, it seems it cannot connect
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
Note that React is running on port 3000 and Django is on port 8000
% npm start <-- React
% python manage.py runserver <-- Django
logs from django and react https://gist.github.com/axilaris/2e0a5ae1887f7d12a226565efa85dd6f
react logs
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 logs
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)
My feeling is something is missing at Django side that channel is not setup properly and not listening to the connection. What am I missing in my setup.
Some suspect:
- channel is not called due to channel socket setup is in user_api
- CORS ?
2
Answers
Problem :-
Look below.
It’s
notifications
.And
It’s
notification
.Path should be same path.
Use as below.
Answer :-
And
The ASGI_APPLICATION should refer to your asgi application correctly use this path:
for better configuration look at django channel documentaion Tutorial:
Tutorial Part 1: Basic Setup