5

是否可以使用 django-channels 访问添加到组中的频道列表?

def consumer(message):
    Group("group_name").add(message.reply_channel)
    channel_list = Group("group_name").???

编辑:

我试图实现的是访问所有频道的会话,例如连接用户列表。

到目前为止,我使用了一个基于数据库的系统来列出连接。但是如果服务器在没有执行我的 ws_disconnect 消费者的情况下关闭,这些连接对象将保留在数据库中,我不希望这样。

编辑2:

要列出已连接的用户,我发现django-channels-presence. 我会测试它。

4

4 回答 4

6

是的,这是可能的。简单的黑客是......

# Get channel_layer function
from channels.asgi import get_channel_layer

# passing group_channel takes channel name
channel_layer = get_channel_layer()
ch_group_list = channel_layer.group_channels('<your group name>')
于 2016-09-12T09:22:06.820 回答
3

我发现channel_layer.group_channels('<your group name>'),上面提到的,在通道 2 上不起作用。所以,我决定将我需要的信息保存在 channel_layer 中,它可以工作。

版本信息

  • 频道==2.1.5
  • aioredis==1.2.0
  • 通道-redis==2.3.2

就我而言,我需要知道组中的频道号,因为我在后台启动 celery beat 以不断将数据推送到频道,但是当组中的最后一个频道断开连接时,我想停止 celery 节拍。

我通过将其存储在 channel_layer 中来计算组中的通道。

连接时

count = getattr(self.channel_layer, self.group_name, 0)
if not count:
    setattr(self.channel_layer, self.group_name, 1)
else:
    setattr(self.channel_layer, self.group_name, count + 1)

断开连接

count = getattr(self.channel_layer, self.group_name, 0)
setattr(self.channel_layer, self.group_name, count - 1)
if count == 1:
    delattr(self.channel_layer, self.group_name)

    # stop my celery beat

于 2019-06-21T06:08:19.200 回答
1

您可以选择将连接在数据库中的房间中的用户持久化。创建房间,在连接时添加用户,在断开连接时删除用户。

from django.db import models
from django.contrib.auth import get_user_model
from asgiref.sync import sync_to_async


# ./models
class Room(models.Model):
    room_name = models.CharField(max_length=150, unique=True)
    users = models.ManyToManyField(get_user_model(), related_name='rooms')

    @classmethod
    @sync_to_async
    def add(cls, room_name, user):
        room, created = cls.objects.get_or_create(room_name=room_name)
        room.users.add(user)
        return created # sockets => join or create



    @classmethod
    @sync_to_async
    def users_count(cls, room_name):
        rooms = cls.objects.filter(room_name=room_name)
        if rooms.exists():
            return rooms.first().users.count()
        return 0

    @classmethod
    @sync_to_async
    def remove_user(cls, user, room_name):
        room = cls.objects.filter(room_name=room_name)
        if room.exists():
            room.users.remove(user)


# ./consumer.py
class YourConsumer(AsyncWebsocketConsumer):

    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'video_%s' % self.room_name
        self.group_users = {self.scope.get('user').id: 1}

        if self.scope.get('user').is_authenticated:
            room = await Room.add(self.room_name, self.scope.get('user'))

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

        await self.accept()

    async def disconnect(self, code):
        # Leave room group
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )
        if self.scope.get('user').is_authenticated:
            await Room.remove_user(self.room_name, self.scope.get('user'))

    async def websocket_receive(self, message):
        count = await Room.users_count(room_name=self.room_name)
        await self.send(json.dumps({
            'type': 'websocket.send',
            'text': 'pong',
            'group': self.room_group_name,
            'room': self.room_name,
            'connections': count
        }))

于 2021-02-07T06:05:27.020 回答
0

我已经测试过,并且通过创建一个(处理管理/创建、添加/删除......)并提供了一种允许我实现我正在搜索的内容的方法,django-channels-presence我很容易成功地列出了连接的用户。GroupRoomGroupchannelget_users()

它还提供了一种在服务器崩溃时清理未删除的添加通道的方法(这不会触发用于从组中删除这些通道的 ws_disconnect 使用者)。它提供了清理过期频道prune_presenceprune_room任务。

于 2016-09-25T23:10:28.893 回答