本文介绍了使用来自 Consumer 类外部的 Django Channels 发送消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个在线游戏,它使用 Django 通道 2.1.5 进行 websockets.

I am building an online game, which uses Django channels 2.1.5 for websockets.

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

I am able to build the connection between the client and the server, and also able to send data between them only inside the consumer class:

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,它位于消费者类中

Now, What I wish to do, is to call the function render, -which is inside the consumer class-, from another module

我试过了:

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"参数.

But failed because I can't use the "self" parameter from outside the class.

有人能想出一种方法来实现我的目标吗?

Can anybody think of a way to achieve my goal?

Ps:这个时候我不关心同步.

Ps: I don't care about synchronization at this occasion.

推荐答案

首先你需要你的消费者实例来订阅一个组.

Firstly you need your consumer instance to subscribe to a group.

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()
...

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

Then if you are outside of your consumer you will need to send a message to that group so that all the consumers that have registered onto the group get the message.

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

但是,您还需要记住在断开连接时将您的使用者从组中移除.

However, you also need to remember to remove your consumer from the group when it disconnects.

class GameConsumer(WebsocketConsumer):
    ....

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

如果您想限制哪些打开的连接收到此渲染消息,您需要相应地构建您的组名.

If you want to limit which open connections get this render message you need to build your group name accordingly.

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

eg if you are thinking about some online game then maybe you include a MATCH-ID in the group name that is shared by all connections for the same match.

对此的一个很好的参考是 channels Layers 文档,但请注意请记住,在生产环境中运行它时,您需要设置一个消息传递层(通常是 Redis).

A good reference for this is the channels Layers documentation but do remember when running this in production you will need a messaging layer (normally Redis) set up.

这篇关于使用来自 Consumer 类外部的 Django Channels 发送消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 01:10