Отправить сообщение с использованием каналов Django из-за пределов класса Consumer - PullRequest
0 голосов
/ 24 ноября 2018

Я создаю онлайн-игру, в которой для веб-сокетов используются каналы Django 2.1.5.

Я могу установить соединение между клиентом и сервером, а также передавать данные между ними только внутрипотребительский класс:

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: меня не волнует синхронизация по этому поводу.

Спасибо заранее.

1 Ответ

0 голосов
/ 27 ноября 2018

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

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 в название группы, которое используется всеми подключениями для одного и того же матча.

Хорошая ссылка на этодокументация Channel Layers , но помните, что при запуске в рабочей среде вам понадобится настроить уровень сообщений (обычно Redis).

...