【问题标题】:How many users are there in the chat session (django-channels)?聊天会话(django-channels)中有多少用户?
【发布时间】:2020-07-23 13:11:06
【问题描述】:

基本上我已经创建了聊天应用程序,但我不知道如何显示有多少用户加入了聊天组。简单地说,我想显示用户的姓名并且他们在线/离线。我尝试过 import Group 但后来我知道它已被弃用,然后尝试 django-channel-presence 但现在能够理解。 请帮忙!

# chat/consumers.py
# Sorry   ????????for my code

import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer, AsyncJsonWebsocketConsumer
from django.contrib.auth import get_user_model
from .models import Message
from django.db.models.signals import post_save
from django.dispatch import receiver

# import channels
# from channels.auth import channel_session_user, channel_session_user_from_http

User = get_user_model()

class ChatConsumer(WebsocketConsumer):

    def new_message(self, data):
        author = data['from']
        author_user = User.objects.filter(username=author)[0]
        message = Message.objects.create(
            author=author_user,
            content=data['message'])
        content = {
            'command': 'new_message',
            'message': self.message_to_json(message)
        }

        return self.send_chat_message(content)

    # def messages_to_json(self, messages):
    #     result = []
    #     for message in messages:
    #         result.append(self.message_to_json(message))
    #     return result

    def message_to_json(self, message):
        return {
            'id': message.id,
            'author': message.author.username,
            'content': message.content,
            'timestamp': str(message.timestamp)
        }

    commands = {
        'new_message': new_message
    }

    # PREDEFINED
# ***************************************************************************************************************************
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        print("self.scope['url_route']['kwargs']['room_name'] : "+self.scope['url_route']['kwargs']['room_name'])

        self.room_group_name = 'chat_%s' % self.room_name
        print("self.room_group_name : " + self.room_group_name)

        print("self.channel_name, : " + self.channel_name)

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

# ***************************************************************************************************************************
    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # ***************************************************************************************************************************
    # Receive message from WebSocket
    # def receive(self, text_data):
    #     data = json.loads(text_data)
    #     message = data['message']
    #     # Send message to room group
    #     async_to_sync(self.channel_layer.group_send)(
    #         self.room_group_name,
    #         {
    #             'type': 'chat_message',
    #             'message': message
    #         }
    #     )   # receives from chat/room.html


    def receive(self, text_data):
        data = json.loads(text_data)
        self.commands[data['command']](self, data)  # determining what command was sent

    def send_chat_message(self, message):
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

# ***************************************************************************************************************************
    # Receive message from room group    # receives from chat/room.html
    # def chat_message(self, event):
    #     message = event['message']
    #
    #     # Send message to WebSocket
    #     self.send(text_data=json.dumps({
    #         'message': message
    #     }))
    #

    def send_message(self, message):
        self.send(text_data=json.dumps(message))

    def chat_message(self, event):
        message = event['message']
        self.send(text_data=json.dumps(message))


我在前端处理消息的脚本

    <script >
        <!------------------------------------------------------------------------------------------------------------------------------>
        <!------------------------------------------------------------------------------------------------------------------------------>

         const roomName = {{room_name}};
         const username = {{ username }};

        const user_count = [];

        <!--  e here represents an event  -->

        const chatSocket = new ReconnectingWebSocket(
            'ws://'
            + window.location.host
            + '/ws/chat/'
            + roomName
            + '/'
        );
        console.log('window location testing : '+window.location.host);

        chatSocket.onmessage = function(e)
        {
            const data = JSON.parse(e.data);
            var message = data['message'];
            var author = data['author'];

            var msgListTag = document.createElement('li');
            var pTag = document.createElement('p');
            var pAuth = document.createElement('p');
            pTag.setAttribute('style', 'white-space: pre;');
            pTag.textContent = message.author+"\r\n";
            pTag.textContent += message.content;

            if(message.author == username)
            {
                msgListTag.className = 'sent' ;
            }
            else
            {
                msgListTag.className = 'replies' ;
            }

            msgListTag.appendChild(pTag);

            document.querySelector('#chat-log').appendChild(msgListTag);

        };
        <!-- from consumers.py "message"  -->

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#chat-message-submit').click();
            }
        };

        <!--  important action  -->

        document.querySelector('#chat-message-submit').onclick = function(e) {
            const messageInputDom = document.querySelector('#chat-message-input');
            const message = messageInputDom.value;

            if(messageInputDom.value == '')
            {
                console.log('Enter a text');
            }
            else
            {
                chatSocket.send(JSON.stringify({
                    'command': 'new_message',
                    'message': message,
                    'from': username
                }));
            }
            messageInputDom.value = '';
        };

    </script>

【问题讨论】:

  • 为您的聊天和聊天成员制作模型。当用户加入聊天时,您添加一个聊天成员对象。然后您可以只计算链接到特定聊天的聊天成员对象的数量
  • @Ken4scholars 但问题是每次用户登录时,都会自动生成一个由 5 个字母数字字符组成的代码作为聊天室的名称。基本上这将是一个一次性的聊天室。所以每次我必须在模型中包含那个聊天室并删除它?
  • 如果您正在运营一个临时聊天室架构,那么只需使用 django 频道的存在,因为它非常适合。他们在文档中有很好的解释,如果你有一个特定的问题,你可以提出代码,显示你尝试过的内容和问题是什么

标签: django django-channels


【解决方案1】:

您可以创建一个单独的模型来跟踪连接和断开连接的用户;用户将在连接到聊天室时被添加到模型中,并在断开连接时被删除。

在models.py中:

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

class Connected(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="connected")
    room_name = models.CharField(max_length=100, null=False)
    channel_name = models.CharField(max_length=100, null=False)
    connect_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user

在 consumer.py 中,创建 2 个函数(connect_userdisconnect_user):

@sync_to_async
def connect_user(room_name, user, channel_name):
    if user:
        Connected.objects.create(user=user room_name=room_name, channel_name=channel_name)
    else:
        pass
    return None


@sync_to_async
    def disconnect_user(room_name, user, channel_name):
    if user:
        try:
            get_object_or_404(Connected, Q(user=user), Q(room_name=room_name), Q(channel_name=channel_name))
        except:
            pass
        else:
            user = get_object_or_404(Connected, Q(user=user), Q(room_name=room_name), Q(channel_name=channel_name))
            user.delete()
    return None

从 consumer.py 调用它们:

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

    # Join room group
    await self.channel_layer.group_add(
        self.room_group_name,
        self.channel_name
    )
    await self.accept()
    # add user to Connected model
    await connect_user(room_name=self.room_name, user=self.scope['user'], channel_name=self.channel_name)

async def disconnect(self, close_code):
    # Leave room group

    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name
    )
    # Remove user from Connetced Model
    await disconnect_user(room_name=self.room_name, user=self.scope['user'], channel_name=self.channel_name)

从那里,您可以运行queryset 来检查用户是否连接到特定的room_name(如果用户存在,则它已连接,否则未连接),您甚至可以检查连接的数量每个room_name的用户。

【讨论】:

    猜你喜欢
    • 2020-11-13
    • 2020-10-06
    • 2020-05-24
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多