[Fixed]-Sending messages to groups in Django Channels 2

44👍

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!

3👍

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.

0👍

Disconnect may not require self.close() since it does this automatically.
Also try to CHECK routing.py file; I had a similar issue but I fixed it by removing AuthMiddlewareStack (I added it back later) and then in my path, I used MyConsumer.as_asgi() instead of just MyConsumer.

Leave a comment