Sending a message to a single user using django-channels

Expanding on @Flip's answer of creating a group for that particular user.

In your python function in your ws_connect function you can add that user into a a group just for them:

consumers.py

from channels.auth import channel_session_user_from_http
from channels import Group

@channel_session_user_from_http
def ws_connect(message):
    if user.is_authenticated:
        Group("user-{}".format(user.id)).add(message.reply_channel)

To send that user a message from your python code:

my view.py

import json
from channels import Group

def foo(user):
    if user.is_authenticated:
        Group("user-{}".format(user.id)).send({
            "text": json.dumps({
            "foo": 'bar'
        })
    })

If they are connected they will receive the message. If the user is not connected to a websocket it will fail silently.

You will need to also ensure that you only connect one user to each user's Group, otherwise multiple users could receive a message that you intended for only a specific user.

Have a look at django channels examples, particularly multichat for how to implement routing, creating the websocket connection on the client side and setting up django_channels.

Make sure you also have a look at the django channels docs.


Little update since Groups work differently with channels 2 than they did with channels 1. There is no Group class anymore, as mentioned here.

The new groups API is documented here. See also here.

What works for me is:

# Required for channel communication
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync


def send_channel_message(group_name, message):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        '{}'.format(group_name),
        {
            'type': 'channel_message',
            'message': message
        }
    )

Do not forget to define a method to handle the message type in the Consumer!

    # Receive message from the group
    def channel_message(self, event):
        message = event['message']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message
        }))