我如何订阅消费者并通知他 django 频道的任何变化

How can i subscribe a consumer and notify him of any changes in django channels

我目前正在构建一个允许用户一起协作和创建事物的应用程序,因为我需要一种不和谐的方式,例如群聊。我需要能够为登录用户订阅项目以获取通知。
我有一个方法 open_project 从用户选择的项目中检索详细信息,我用它来订阅该项目的任何更新。

所以我可以想到两种方法来做到这一点。我在连接函数中创建了一个实例变量,如下所示:

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 列表中,但是这不起作用(我认为)每当新用户连接到 websocket 时,他都会获得自己的项目消费者。

我想到的第二种方法是创建一个只有 1 个实例并跟踪所有连接到项目的用户的管理 class。我还没有尝试过这个,因为我想要一些关于我是否在正确的球场挥杆的反馈。感谢任何和所有反馈。

编辑 1: 我忘了在问题中添加 userjoinedMessage 方法,这个方法只是为了模仿未来的机制和反馈,看看我的解决方案是否真的有效,但这里是:

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

请注意,我试图引用消费者的实例。

我还将尝试实现一个消费者管理器,其作用是跟踪消费者正在浏览哪些项目并将更新发送到相关渠道。

是的,这可能是一种糟糕的做事方式,我应该被带回去枪毙,但我有一个解决我的问题的方法。我制作了一个 ProjectManager class 来处理项目用户的订阅和更新:

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 class 并将其分配给一个变量。

from django.apps import AppConfig
from .manager import ProjectManager


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

然后我在我的 consumers.py 文件中使用它。我从 projectconfig class 导入管理器,并在其连接时将其分配给创建的消费者内的实例变量:

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

并且每当我调用 open_project 时,我都会使用从 front-end 收到的给定项目 ID 订阅该项目:

 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,因此将使用它。 当然,我仍然乐于接受建议,并且总是乐于了解更多信息。

从问题来看,问题是如何保存 projectSessions 并使其可跨消费者的多个实例访问。您可以将其保存在数据库中,而不是尝试将其保存在内存中。它是一个以项目为键的字典。您可以将其设为 table 并带有 Project 模型的 ForeignKey。 这样,它就会被持久化,如果您决定跨多个服务器扩展通道,即使跨多个通道服务器实例检索它也不会有问题。 此外,如果您觉得传统数据库会减慢会话的检索速度,那么您可以使用更快的存储系统,如 redis