Sending a message to a single user using django-channels

lukeaus picture lukeaus · Sep 5, 2016 · Viewed 16.9k times · Source

I have been trying out django-channels including reading the docs and playing around with the examples.

I want to be able to send a message to a single user that is triggered by saving a new instance to a database.

My use case is creating a new notification (via a celery task) and once the notification has saved, sending this notification to a single user.

This sounds like it is possible (from the django-channels docs)

...the crucial part is that you can run code (and so send on channels) in response to any event - and that includes ones you create. You can trigger on model saves, on other incoming messages, or from code paths inside views and forms.

However reading the docs further and playing around with the django-channels examples, I can't see how I can do this. The databinding and liveblog examples demonstrate sending to a group, but I can't see how to just send to a single user.

Any suggestions would be much appreciated.

Answer

lukeaus picture lukeaus · Sep 23, 2016

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.