Django channels: уведомления о сообщениях не работают должным образом

Я пишу модуль django, который обрабатывает сообщения в реальном времени в паре с уведомлениями. Пока что:
разговор может происходить только между не более чем 2 пользователями. после каждого сообщения должно быть отправлено уведомление.

В настоящее время я работаю над тем, чтобы уведомления отображались, и проблема в том, что уведомление отображается на странице профиля отправителя, а не в профиле получателя. Я не могу понять, где моя ошибка

Вот что я сделал: consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from .models import Chat, ChatRoom
from accounts.models import User
from asgiref.sync import sync_to_async
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from asgiref.sync import async_to_sync

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_id = self.scope['url_route']['kwargs']['room_id']
        self.room_group_name = 'chat_%s' % self.room_id

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        recipient = text_data_json['recipient']

        self.user_id = self.scope['user'].id

        # Find room object
        room = await database_sync_to_async(ChatRoom.objects.get)(pk=self.room_id)
        print('ok1')

        # Create new chat object
        chat = Chat(
            content=message,
            sender=self.scope['user'],
            room=room,

        )
        print('ok2')
        await database_sync_to_async(chat.save)()
        print("ok3")
        # get the recipient user
        recipient_user = await database_sync_to_async(User.objects.get)(id=recipient)
        print("ok4")

        await sync_to_async(chat.recipient.add)(recipient_user.id)
        print("ok5")
        await database_sync_to_async(chat.save)()


        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'user_id': self.user_id
            })

        # Send a notification to the recipient
        await self.channel_layer.send(
            recipient_user.username,
            {
                'type': 'notification',
                'message': message
            }
        )
        await self.send_notification(f'New message from {self.user_id}')
        print('notification has been created')

    async def chat_message(self, event):
        message = event['message']
        user_id = event['user_id']

        await self.send(text_data=json.dumps({
            'message': message,
            'user_id': user_id
        }))

    async def send_notification(self, message):
        await self.send(text_data=json.dumps({
            'type': 'notification',
            'message':message

        }))

и вот мой код room.js, который представляет собой код javascript, обрабатывающий логику отображения сообщений и уведомлений:

chatSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    console.log("data",data)
    console.log("datatype",data.type)
    var message_type = data.type;
    console.log("message type",message_type)
    if(message_type === 'notification'){
            $("#notification-bar2").text(data.message);
            $("#notification-bar2").show();
        }
    if(message_type !== 'notification'){
    const messageElement = document.createElement('div')
    const userId = data['user_id']
    const loggedInUserId = JSON.parse(document.getElementById('user_id').textContent)
    console.log(loggedInUserId)
    messageElement.innerText = data.message

    if (userId === loggedInUserId) {
        messageElement.classList.add( 'relative', 'max-w-xl', 'px-4', 'py-2', 'text-gray-700', 'bg-gray-100','rounded', 'shadow','flex', 'justify-end','message', 'sender','block')
    } else {
        messageElement.classList.add('relative', 'max-w-xl', 'px-4', 'py-2', 'text-gray-700', 'bg-gray-100','rounded', 'shadow','flex', 'justify-start','message', 'receiver','block')
    }

    chatLog.appendChild(messageElement)

    if (document.querySelector('#emptyText')) {
        document.querySelector('#emptyText').remove()
    }
    }
};

Я очень запутался в том, почему это может быть, и быть свежим, начиная с каналов, есть все еще довольно много вещей, которые я не понимаю супер хорошо, поэтому любая помощь короля будет высоко оценена! Я более чем счастлив предоставить дополнительный код, если необходимо

В вашей функции получения есть только получатель и подключенный пользователь. Этот код берет получателя, который поставляется с сообщением, и отправляет его этому пользователю (получателю), сообщая ему, что оно пришло от этого пользователя (отправителя). Сообщение уже сопровождается тегом получателя, которому оно отправляется, когда оно попадает в вебсокет. Нам нужно избавиться от этого и отслеживать всех наших подключенных пользователей внутри объекта ChatRoom. Вы можете просто обработать это в представлении или когда пользователь подключается к вебсокету. Когда сообщение отправлено, получите каждого пользователя-получателя в комнате, а это должны быть все пользователи, кроме пользователя, который отправил объект.

    print('ok2')
    await database_sync_to_async(chat.save)()
    print("ok3")
    # get the recipient user
    # database_sync_to_async function that gets the list of users
    # dont forget to call users.remove(sender)
    for each in users:
        recipient_user = each
        print("ok4")

        await sync_to_async(chat.recipient.add)(recipient_user.id)
        print("ok5")
    await database_sync_to_async(chat.save)()

Похоже, вы пытаетесь отправить уведомление двумя разными способами, но делаете это неправильно.

        # Send a notification to the recipient
        await self.channel_layer.send(
            recipient_user.username,
            {
                'type': 'notification',
                'message': message
            }
        )
        await self.send_notification(f'New message from {self.user_id}')
        print('notification has been created')

Первый метод пытается отправить его через канальный уровень, что является правильным способом, учитывая, что текущим каналом является канал отправителя, поэтому вам нужно передать его через канальный уровень в канал получателя. Проблема в том, что вы используете неправильное имя обработчика. Вы используете notification в качестве типа вместо send_notification, поэтому он никогда не будет обработан. Во втором случае вы вызываете функцию send_notification непосредственно в текущем канале, который является каналом отправителя, поэтому сообщение будет отправлено отправителю, а не получателю. Весь блок кода выше должен быть заменен на:

    # Send a notification to the recipient
    await self.channel_layer.send(
        recipient_user.username,
        {
            'type': 'send_notification',
            'message': f'New message from {self.user_id}'
        }
    )
Вернуться на верх