Sending messages to groups in Django Channels 2
I had a similar issue to this for a while too, though the reason my group_send was not working was because a websocket was not actually connected.
When testing the dev server reloaded which disconnected the socket, so subsequent calls were not getting run by the consumer. Refreshing the frontend reconnected the socket and group_send started working.
Though this doesn't directly address the question I hope this might help somebody.
I found the solution while writing this questions and thought that someone else might also make use of it! Since most of the questions out here are about channels version prior to 2.0 and above, this is how you should handle group_send events in your consumers.
The problem did not only lie in how I used the group_send
function though, I had wrongly assumed that adding the groups class variable to my EventConsumer should automatically add it to that/those groups, it does NOT! You have to add groups manually in the connect
class function and remove groups in the disconnect
function!
The problem then also lied in that my consumer did not have proper event handlers specified. In my view file, where the alarm request is taken in, I had set the 'type' to 'test'. Test was not reflected in my EventConsumer class so the event could not be processed. As noted in the multichat example here on line number 146, the helper functions get called depending on the type of the event sent. So an event type of 'event.alarm' should have a corresponding function of event_alarm
in your consumer! Simple, but not so well documented :). Here is what the final solution looked like:
In consumers.py
, note the group_add
in connect and the group_discard
in disconnect!
class EventConsumer(JsonWebsocketConsumer):
def connect(self):
async_to_sync(self.channel_layer.group_add)(
'events',
self.channel_name
)
self.accept()
def disconnect(self, close_code):
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("Received event: {}".format(content))
self.send_json(content)
# ------------------------------------------------------------------------------------------------------------------
# Handler definitions! handlers will accept their corresponding message types. A message with type event.alarm
# has to have a function event_alarm
# ------------------------------------------------------------------------------------------------------------------
def events_alarm(self, event):
self.send_json(
{
'type': 'events.alarm',
'content': event['content']
}
)
So, the above function events_alarm
gets called from the following group_send
:
from django.shortcuts import HttpResponse
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
def alarm(req):
layer = get_channel_layer()
async_to_sync(layer.group_send)('events', {
'type': 'events.alarm',
'content': 'triggered'
})
return HttpResponse('<p>Done</p>')
Please let me know if you need any more clarifications to the question/answer! Cheers!