我如何订阅消费者并通知他 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
我目前正在构建一个允许用户一起协作和创建事物的应用程序,因为我需要一种不和谐的方式,例如群聊。我需要能够为登录用户订阅项目以获取通知。
我有一个方法 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