TL;DR
Want this flow:
ws://...
websocket client 1 <-----------> websocket client 2
^
|
server (send messages via views)
So I have the following:
views.py
def alarm(request):
layer = get_channel_layer()
async_to_sync(layer.group_send)('events', {
'type': 'events.alarm',
'content': 'triggered'
})
return HttpResponse('<p>Done</p>')
consumers.py
class EventConsumer(JsonWebsocketConsumer):
def connect(self):
print('inside EventConsumer connect()')
async_to_sync(self.channel_layer.group_add)(
'events',
self.channel_name
)
self.accept()
def disconnect(self, close_code):
print('inside EventConsumer disconnect()')
print("Closed websocket with code: ", close_code)
async_to_sync(self.channel_layer.group_discard)(
'events',
self.channel_name
)
self.close()
def receive_json(self, content, **kwargs):
print('inside EventConsumer receive_json()')
print("Received event: {}".format(content))
self.send_json(content)
def events_alarm(self, event):
print('inside EventConsumer events_alarm()')
self.send_json(
{
'type': 'events.alarm',
'content': event['content']
}
)
in routing.py
application = ProtocolTypeRouter({
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns,
)
)
),
})
where websocket_urlpatterns is
websocket_urlpatterns = [
url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer),
url(r'^ws/event/$', consumers.EventConsumer),
]
urls.py
urlpatterns = [
url(r'^alarm/$', alarm, name='alarm'),
]
when I call /alarm/
, only the HTTP request is made and the message is not sent to the websocket
The following are the logs:
[2018/09/26 18:59:12] HTTP GET /alarm/ 200 [0.07, 127.0.0.1:60124]
My intention is to make django view send to a group (use case would be for a server to send notification to all connected members in the group).
What setting am I missing here.
I am running django channels 2.1.3 with redis as backend. The CHANNELS_LAYERS etc. have all been setup.
Reference Links:
EDIT: I could send the message using the websocket-client from the view
from websocket import create_connection
ws = create_connection("ws://url")
ws.send("Hello, World")
But is it possible to send without using the above (donot wan't to create a connection)?
Source code: chat-app
credits to @Matthaus Woolard for making the concept pretty clear.
So this was the problem:
The client had disconnected when I tried to send the message from the django view. This happened as the server restarted upon code change. I refreshed the browser and it started to work.
Silly mistake
So to summarize:
Add the following in connect() in case of Synchronous consumer:
async_to_sync(self.channel_layer.group_add)('events', self.channel_name)
or add this incase of Async Consumer:
await self.channel_layer.group_add('events', self.channel_name)
create a view as follows:
def alarm(request):
layer = get_channel_layer()
async_to_sync(layer.group_send)('events', {
'type': 'events.alarm',
'content': 'triggered'
})
return HttpResponse('<p>Done</p>')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With