Как я могу подписаться на потребителя и уведомлять его о любых изменениях в каналах Django? - PullRequest
0 голосов
/ 13 мая 2019

В настоящее время я создаю приложение, которое позволяет пользователям совместно работать и создавать вещи, так как мне требуется что-то вроде раздора, такого как групповой чат. Мне нужно иметь возможность подписаться на зарегистрированных пользователей на проект для уведомлений.
У меня есть метод open_project, который извлекает подробности из проекта, выбранного пользователем, который я использую, чтобы подписать его на любые обновления для этого проекта.

Так что я могу придумать 2 способа сделать это. Я создал переменную экземпляра в моей функции подключения, например:

def connect(self):
    print("connected to projectconsumer...")
    self.accept()
    self.projectSessions = {}

А вот метод open_project:

def open_project(self, message):

    p = Project.objects.values("projectname").get(id=message)
    if len(self.projectSessions) == 0:
        self.projectSessions[message] = []
        pass
    self.projectSessions[message] = self.projectSessions[message].append(self)
    print(self.projectSessions[message])
    self.userjoinedMessage(self.projectSessions[message])
    message = {}
    message["command"] = "STC-openproject"
    message["message"] = p
    self.send_message(json.dumps(message))

Затем, когда пользователь открывает проект, он добавляется в список projectSessions, однако это не работает (я думаю), когда новый пользователь подключается к веб-сокету, он получает своего собственного потребителя проекта.

Второй способ, который я задумал сделать, - это создать управляющий класс, который имеет только 1 экземпляр и отслеживает всех пользователей, подключенных к проекту. Я еще не пробовал это, так как я хотел бы получить некоторую обратную связь, если я даже качаюсь в правильном парке мячей. Любые отзывы приветствуются.

РЕДАКТИРОВАТЬ 1: Я забыл добавить метод userjoinedMessage к вопросу, этот метод просто для имитации будущей механики и для обратной связи, чтобы увидеть, действительно ли мое решение работает, но вот оно:

    def userjoinedMessage(self, pointer):
        message = {}
        message["command"] = "STC-userjoinedtest"
        message["message"] = ""
        pointer.send_message(json.dumps(message))

обратите внимание, что я пытаюсь сослаться на экземпляр потребителя.

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

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Вопрос заключается в том, как сохранить projectSessions и сделать его доступным для нескольких пользователей.Вместо того, чтобы пытаться сохранить его в памяти, вы можете сохранить в базе данных.Это словарь с проектом в качестве ключа.Вы можете сделать это с помощью ForeignKey для модели проекта.Таким образом, он сохраняется и не будет проблем с его извлечением даже на нескольких экземплярах сервера каналов, если вы когда-нибудь решите масштабировать свои каналы на нескольких серверах.Кроме того, если вы чувствуете, что традиционная база данных замедлит получение сеансов, вы можете использовать более быстрые системы хранения, такие как redis

0 голосов
/ 13 мая 2019

Правильно, это, вероятно, ужасный способ сделать что-то, и я должен быть убран обратно и расстрелян за это, но у меня есть решение моей проблемы. Я создал класс ProjectManager, который обрабатывает подписки и обновления для пользователей проекта:

import json

class ProjectManager():

    def __init__(self):
        if(hasattr(self, 'projectSessions')):
            pass
        else:
            self.projectSessions = {}




    def subscribe(self, projectid, consumer):
        print(projectid not in self.projectSessions)
        if(projectid not in self.projectSessions):
            self.projectSessions[projectid] = []
        self.projectSessions[projectid].append(consumer)
        self.update(projectid)


    def unsubscribe(self, projectid, consumer):
        pass

    def update(self, projectid):
        if projectid in self.projectSessions:
            print(self.projectSessions[projectid])
            for consumer in self.projectSessions[projectid]:
                message = {}
                message["command"] = "STC-userjoinedtest"
                message["message"] = ""
                consumer.send_message(json.dumps(message))
                pass

в моем файле apps.py я инициализирую вышеупомянутый класс ProjectManager и присваиваю его переменной.

from django.apps import AppConfig
from .manager import ProjectManager


class ProjectConfig(AppConfig):
    name = 'project'
    manager = ProjectManager()

Который я затем использую в своем файле consumers.py. Я импортирую менеджер из класса projectconfig и назначаю его переменной экземпляра внутри созданного потребителя, когда он подключен:

    def connect(self):
        print("connected to projectconsumer...")
        self.accept()
        self.manager = ProjectConfig.manager

и всякий раз, когда я звоню open_project, я подписываюсь на этот проект с указанным идентификатором проекта, полученным из внешнего интерфейса:

 def open_project(self, message):

        p = Project.objects.values("projectname").get(id=message)
        self.manager.subscribe(message, self)
        message = {}
        message["command"] = "STC-openproject"
        message["message"] = p
        self.send_message(json.dumps(message))

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

...