python - 使用来自消费者类外部的 Django Channels 发送消息

标签 python django websocket django-channels

我正在构建一个在线游戏,它使用 Django Channels 2.1.5 for websockets。

我能够在客户端和服务器之间建立连接,也能够仅在消费者类内部在它们之间发送数据:

from channels.generic.websocket import WebsocketConsumer
import json
from . import controller

class GameConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()
        print("Wohooo .. Connected to client!")
        self.render()
        controller.startTurn()

    def render(self, type="render", message=None):
        self.send(controller.renderMap(type, message))

    def disconnect(self, close_code):
        print("WebSocket connection is lost...")

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        controller.handleRecieved(text_data)
...

现在,我想做的是从另一个模块调用函数render,-它在消费者类中-

我试过这个:

from .. import consumer

def sendDeployments(owner, armies):
    type = "renderDeployments"
    message = owner + " has " + str(armies) + " to deploy"
    dummyConsumer = consumer.GameConsumer()
    consumer.GameConsumer.render(type, message)

但是失败了,因为我不能从类外使用“self”参数。

有人能想出办法实现我的目标吗?

Ps:我这个场合不关心同步

最佳答案

首先,您需要您的消费者实例订阅一个群组。

from asgiref.sync import async_to_sync

class GameConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()
        self.render()
        async_to_sync(self.add_group)('render_updates_group') 
        controller.startTurn()
...

然后,如果您在您的消费者之外,您将需要向该组发送一条消息,以便所有注册到该组的消费者都能收到消息。

from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync

def sendDeployments(owner, armies):
    type = "renderDeployments"
    message = owner + " has " + str(armies) + " to deploy"
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        'render_updates_group',
        {'type': 'render', 'message': message}
    )

但是,您还需要记住在断开连接时将您的消费者从组中移除。

class GameConsumer(WebsocketConsumer):
    ....

    def disconnect(self, close_code):
         async_to_sync(self.group_name)('render_updates_group')

如果你想限制哪些打开的连接得到这个渲染消息,你需要相应地建立你的组名。

例如,如果您正在考虑一些在线游戏,那么您可能会在群组名称中包含一个 MATCH-ID,该 ID 由同一场比赛的所有连接共享。

一个很好的引用是 channels Layers documentation但请记住,在生产环境中运行它时,您需要设置一个消息传递层(通常是 Redis)。

关于python - 使用来自消费者类外部的 Django Channels 发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53461830/

相关文章:

python - 在 Django 中,我如何返回与模型相关的项目总数?

php - 如何使 "server"PHP 脚本与其他脚本通信

c++ - 如何在 PNaCl 中等待 WebSocket 响应

python - 如何仅打印输出的最大值

python - 如何将项目从一个 QTreeWidget 移动到另一个 QTreeWidget 并跟踪信息?

python - Docker 容器中的 Django 单元测试 : ModuleNotFoundError: No module named 'code.x' ; 'code' is not a package

sql-server - Django 连接到 SQL Server - django/sql_server - pyodbc

javascript - json.parse 第一次运行两次字符串,第二次运行对象,为什么?

python - 删除连续的字母重复项

python - Tweepy 光标搜索查询可以遍历从文件加载的单词列表吗?