如何添加收件箱通知系统并从一个用户 django 频道中删除消息

How to add inbox notification system and delete message from one user django channels

我正在尝试使用 Django、Django-rest-framework 和 Django-channels 构建一个类似 Messenger 的应用程序。 现在我只能将消息从一个用户发送到另一个用户。但我想添加这样的功能,新消息将与用户名一起位于收件箱的顶部,并且一个用户可以从他身边删除消息,就像信使,什么应用程序等。当有人发送消息时,他的消息将打开顶部并将显示通知。 我找不到完美的模型设计和完美的系统。

Model.py

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()


class Message(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE,
                               related_name='sender_messages')
    receiver = models.ForeignKey(User, on_delete=models.CASCADE,
                                 related_name='receiver_messages')
    text = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '{} to {}'.format(self.sender.name, self.receiver.name)

消费者

import json

from asgiref.sync import async_to_sync
from django.contrib.auth import get_user_model
from channels.generic.websocket import WebsocketConsumer

from .models import Message

User = get_user_model()


class ChatConsumer(WebsocketConsumer):

    def connect(self):
        """
        Join channel group by chatname.
        """
        self.group_name = 'chat_{0}'.format(self.scope['url_route']['kwargs']['chatname'])

        async_to_sync(self.channel_layer.group_add)(
            self.group_name,
            self.channel_name,
        )

        self.accept()

    def disconnect(self, close_code):
        """
        Leave channel by group name.
        """
        async_to_sync(self.channel_layer.group_discard)(
            self.group_name,
            self.channel_name
        )

    def receive(self, text_data):
        """
        Receive message from websocket and send message to channel group.
        """
        text_data_json = json.loads(text_data)
        name = text_data_json['name']
        message = text_data_json['message']

        # Store message.
        receiver = User.objects.get(
            name=self.group_name.replace('chat_', '')
                .replace(self.scope['user'].name, '')
                .replace('-', ''))
        Message(sender=self.scope['user'], receiver=receiver, text=message).save()

        async_to_sync(self.channel_layer.group_send)(
            self.group_name,
            {
                'type': 'chat_message',
                'name': name,
                'message': message,
            }
        )

    def chat_message(self, event):
        """
        Receive message from channel group and send message to websocket.
        """
        self.send(text_data=json.dumps({
            'name': event['name'],
            'message': event['message'],
        }))

查看


class HomeView(LoginRequiredMixin, TemplateView):
    template_name = 'home.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # List all users for chatting. Except myself.

        context['users'] = User.objects.exclude(id=self.request.user.id) \
            .values('name')
        context['users'] = User.objects.exclude(gender=self.request.user.gender)
        return context


class ChatHomeApi(viewsets.ModelViewSet):
    serializer_class = InboxRetrieveSerializer
    authentication_classes = [TokenAuthentication]
    pagination_class = GeneralPagination

    def get_queryset(self):
        return Chat_Inbox.objects.filter(sender=self.request.user)


class ChatView(LoginRequiredMixin, TemplateView):
    template_name = 'chat.html'

    def dispatch(self, request, **kwargs):
        # Get the person we are chatting with, if not exist raise 404.
        receiver_name = kwargs['chatname'].replace(
            request.user.name, '').replace('-', '')
        kwargs['receiver'] = get_object_or_404(User, name=receiver_name)
        return super().dispatch(request, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['receiver'] = kwargs['receiver']
        return context


class MessagesAPIView(LoginRequiredMixin, View):

    def get(self, request, chatname):
        # Grab two users based on the chat name.
        users = User.objects.filter(name__in=chatname.split('-'))
        # Filters messages between this two users.
        result = Message.objects.filter(
            Q(sender=users[0], receiver=users[1]) | Q(sender=users[1], receiver=users[0])
        ).annotate(
            name=F('sender__name'), message=F('text'),
        ).order_by('date_created').values('name', 'message', 'date_created')

        return JsonResponse(list(result), safe=False)


所以基本上,我想在收件箱顶部显示新消息,用户可以从他这边删除消息,这可能不会影响其他用户。 提前致谢

对于订购,您可以将时间戳与所有消息一起发送并存储该时间戳。

现在在检索消息时,您可以在 Django 中使用 order_by 检索它们。

例如,

def receive(self, text_data): 
    text_data_json = json.loads(text_data)
    name = text_data_json['name']
    message = text_data_json['message']
    timestamp = timezone.now()
    # Store message.
    receiver = User.objects.get(
        name=self.group_name.replace('chat_', '')
            .replace(self.scope['user'].name, '')
            .replace('-', ''))
    Message(sender=self.scope['user'], receiver=receiver, text=message).save()

    async_to_sync(self.channel_layer.group_send)(
        self.group_name,
        {
            'type': 'chat_message',
            'name': name,
            'message': message,
            'timestamp': timestamp.isoformat()
        }
    )


async def chat_message(self, event):
    # Send message to WebSocket
    await self.send(text_data=json.dumps({
        'message': 'Message Received Successfully',
        'data': {
            'message': event['message'],
            'message_type': event['message_type'],
            'timestamp': event['timestamp']
        }
    }))