Sending a message to a single user using django-channels
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 communicationfrom channels.layers import get_channel_layerfrom asgiref.sync import async_to_syncdef 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 }))
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_httpfrom channels import Group@channel_session_user_from_httpdef 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 jsonfrom channels import Groupdef 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.
In Channels 2, you can save self.channel_name
in a db on connect method that is a specific hash for each user. Documentation here
from asgiref.sync import async_to_syncfrom channels.generic.websocket import AsyncJsonWebsocketConsumerimport jsonclass Consumer(AsyncJsonWebsocketConsumer): async def connect(self): self.room_group_name = 'room' if self.scope["user"].is_anonymous: # Reject the connection await self.close() else: # Accept the connection await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() print( self.channel_name )
Last line returns something like specific.WxuYsxLK!owndoeYTkLBw
This specific hash you can save in user's table.