How to send user notifications using django-channels 2.0?
Asked Answered
I

4

2

I am working on a chat app that has Rooms. Each room has two users. A user can be in multiple rooms i.e, a user has multiple rooms. And now he is chatting in one room. But he receives a message in another room. I would like to notify about the message from other room to the user. How should I implement this?

Currently a websocket connection is established as: ws://localhost:8000/chat/int<room_id>/

And the group_name is named as "room"+room_id. and So far I have:

async def connect(self):
    room_id = self.scope['url_route']['kwargs']['room_id']
    await self.channel_layer.group_add(
            "room"+room_id,
            self.channel_name
        )
    await self.accept()

async def receive(self, text_data):
    await self.channel_layer.group_send(
        self.room_name,
        {
            'type': 'chat_message',
            'message': json.loads(text_data)
        }
    )
async def chat_message(self, event):
    await self.send(text_data=json.dumps({
        'message': event['message']
    }))

Django 2.x django-channels 2.x python 3.6

Indulge answered 30/7, 2018 at 17:21 Comment(0)
S
1

You need at least two models Message, MessageThread. When the user connects to the socket the channel is added to each thread group that the user is included in. You also have to add the channel_name to the user session.

messaging/models.py

class MessageThread(models.Model):
    title = models.CharField()
    clients = models.ManyToManyField(User, blank=True)

class Message(models.Model):
    date = models.DateField()
    text = models.CharField()
    thread = models.ForeignKey('messaging.MessageThread', on_delete=models.CASCADE)
    sender = models.ForeignKey(User, on_delete=models.SET_NULL)

chat/consumers.py

class ChatConsumer(WebSocketConsumer):
    def connect(self):
        if self.scope['user'].is_authenticated:
            self.accept()
            # add connection to existing groups
            for thread in MessageThread.objects.filter(clients=self.scope['user']).values('id'):
                async_to_sync(self.channel_layer.group_add)(thread.id, self.channel_name)
            # store client channel name in the user session
            self.scope['session']['channel_name'] = self.channel_name
            self.scope['session'].save()

    def disconnect(self, close_code):
        # remove channel name from session
        if self.scope['user'].is_authenticated:
            if 'channel_name' in self.scope['session']:
                del self.scope['session']['channel_name']
                self.scope['session'].save()
            async_to_sync(self.channel_layer.group_discard)(self.scope['user'].id, self.channel_name)
Santos answered 2/8, 2018 at 13:11 Comment(3)
Will a notification app look similar? Do we need a notification thread to channel incoming notifications or can we do that somewhere else?Parquet
For notifications you only need two models: User and Notification. On connect set the scope to the currently authenticated user. Set up a post_save signal on your Notification model to trigger a consumer method to message the notification object's user.Santos
@Parquet meant to say set the group_name to the user on connect.Santos
A
0

I do something similar, you can try something like this:

connect(message):
    // however you get your chatroom value from the socket
    Group("%s" % chatroom).add(message.reply_channel)

message(message):
    message = json.loads(message.content['text'])
    chatroom = message['chatroom']  
    Group("%s" % chatroom).send({
            "text": json.dumps({
                "id": "newuser",
                "username": message['username'],
                "message": message['message']
            })
        })

I might have misread your question. Maybe something more like:

Create a unique id for each user and use that value as the 'chatroom', then send each message with a chatroom number and the user number that it should go to. Django can interpret the user id and sent the message to the right channel, then have the Javascript interpret it the message and roomnumber to bring them to the right page?

That is an interesting idea

Aime answered 31/7, 2018 at 20:18 Comment(2)
It's django-channels 2.x. There is a major change from 1.x to 2.x.Indulge
Gotcha... Guess I can leave this for others just in case, my bad lolAime
I
0

(idea:)I opened two sockets:

  1. one for current room which user is texting in
  2. the second for chat rooms list (a hidden base chatroom created as well; better to say: a channel layer that belongs to chat rooms list),

then on every message received from any user in the first explained channel(above), I will send proper reply to both of the sockets.

example at here: chatroom.subtionary.com (just click on one chatroom and enter with email) it also reorder the chat rooms list and pulse the element and also write the last message of each chatroom under its element, also enjoy reply and delete options!!

(I know this is the laziest way, but works well)

Innervate answered 11/9, 2019 at 5:32 Comment(0)
M
-2

django code for circulars and notifications system using class based and using serializer function with hole project code in step by step

Martz answered 26/7, 2023 at 10:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.