Можно ли вывести список каналов, хранящихся в группе?

Можно ли получить доступ к списку каналов, добавленных в группу, с помощью django-channels?

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

РЕДАКТИРОВАТЬ:

Я пытаюсь добиться доступа ко всем сессиям всех каналов, например, к списку подключенных пользователей.

До сих пор я использую систему на основе базы данных, в которой перечислены соединения. Но если сервер завершит работу без выполнения моих потребителей ws_disconnect, эти объекты соединений останутся в базе данных, а я этого не хочу.

ИЗМЕНИТЬ 2:

Чтобы вывести список подключенных пользователей, я нашел django-channels-presence. Я это проверю.


person vmonteco    schedule 12.09.2016    source источник


Ответы (4)


Да, это возможно. А легкий взлом ...

# 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>')
person Raja Simon    schedule 12.09.2016
comment
Хороший! Можно ли получить доступ к некоторой информации, такой как связанный сеанс / пользователь? :) - person vmonteco; 12.09.2016
comment
каналы поставляются с @channel_session_user_from_http декоратором, а в функции потребителей вы можете получить пользователя из message.user, это то, что вы хотите - person Raja Simon; 12.09.2016
comment
Я знаю это, но разве это не применимо только к текущему параметру потребителя message? то, что я получил с функцией get_channel_layer(),group_channels(), было словарём, связывающим строки с числами с плавающей запятой: ({'websocket.send!dLCNWvEM': 1473714104.796983}). Как я могу получить доступ к настройкам каждого канала? Например, чтобы вывести список подключенных пользователей? - person vmonteco; 13.09.2016
comment
Не работает на каналах 3.0.3. - person Shree Ranga Raju; 22.06.2021
comment
@ShreeRangaRaju Мм, позволь мне проверить и вернуться к тебе по этому поводу ... - person Raja Simon; 22.06.2021

Я обнаружил, что channel_layer.group_channels('<your group name>'), упомянутый выше, не работает на каналах 2. Итак, я решил сохранить информацию, которая мне нужна, в channel_layer, и она заработала.

информация о версии

  • каналы == 2.1.5
  • aioredis == 1.2.0
  • каналы-Redis == 2.3.2

В моем случае мне нужно знать номер каналов в группе, потому что я запускаю ритм сельдерея в фоновом режиме для продолжения передачи данных на каналы, но когда последний канал в группе отключается, я хочу остановить ритм сельдерея.

Я считаю каналы в группе, сохраняя их в 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

person dhq    schedule 21.06.2019
comment
Это опасно. Асинхронные потребители могут привести к состоянию гонки, и нет события / метода отключения, на которые вы можете положиться. - person Yannic Hamann; 14.01.2020

При желании вы можете сохранить пользователей, подключенных к комнате в базе данных. Создайте комнату, добавьте пользователей при подключении и удалите пользователей при отключении.

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
        }))

person p8ul    schedule 07.02.2021

Я протестировал django-channels-presence, и мне легко удалось составить список подключенных пользователей для Group путем создания Room (который обрабатывает Group управление / создание, channel добавление / удаление ...) и предоставляет метод get_users(), который позволяет мне достичь того, что я искал.

Он также обеспечивает способ очистки добавленных каналов, которые не удаляются в случае сбоя сервера (при этом не запускается потребитель ws_disconnect, который используется для удаления этих каналов из группы). Он предоставляет задачи prune_presence и prune_room, которые очищают просроченные каналы.

person vmonteco    schedule 25.09.2016
comment
Ответ бесполезен без фрагмента - person Paullo; 15.06.2019