Повторное использование существующего веб-сокета в каналах Django

Я полусерьезно возился с Python, чтобы создать своего рода сервер-привратник между системой с ограниченным доступом и приложением GAE. Я собираюсь начать с более общего вопроса, прежде чем перейти к конкретному вопросу, связанному с кодом.

Обзор

Система ограниченного доступа настраивается с помощью приложения Python командной строки, которое открывает соединение WebSocket с приложением Django Channels, запущенным на промежуточном сервере, и начинает отправлять регулярные контрольные кадры, что подтверждает приложение Django. Все идет нормально. Время от времени приложение Django будет получать HTTP-запрос, который будет проверять, и, если он пройдет, отправит инструкцию другой системе. Теперь, чтобы сделать его эффективным, у меня возникла идея повторно использовать существующее соединение WS и скопировать на него кадр инструкции.

Вопрос

Django позволяет мне легко получать кадры в сокет и действовать в соответствии с указанными кадрами. У меня проблемы с отправкой сообщения по существующему каналу: я не могу на всю жизнь вызвать метод WebsocketConsumer.send(), даже через оболочку, из метода, который не у потребителя, но определен в другом месте и принимает потребителя в качестве параметра (лучшее, что я мог придумать до сих пор). Возможно ли это вообще (этот вопрос указывает на самом деле это невозможно)?

Заранее благодарим за любые указатели. Если будет, завтра я могу обновить вопрос своими классами.


person Zalán Meggyesi    schedule 09.07.2018    source источник


Ответы (1)


Может быть, уже слишком поздно, но вам нужно отправить сообщение прямо на канал или группу, которую приложение прослушивает. Каналы направят ваше сообщение к соответствующему методу потребителя.

Итак, если вы хотите вызвать метод send_message у потребителя, обслуживающего ваше другое приложение (скажем, channel1): вы должны сделать это:

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

channel_layer = get_channel_layer()
sync_to_async(channel_layer.send)("channel1", {
    "type": "send.message",
    "text": "Hello there!",
})

Это можно сделать в любом месте вашего кода.

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

person Ken4scholars    schedule 20.01.2019
comment
Оказалось, слишком поздно, но поскольку вы хотя бы ответили на вопрос, вы действительно заслуживаете общепринятого ответа. - person Zalán Meggyesi; 22.01.2019
comment
Здравствуйте, сомневаюсь, как узнать название канала? Я пытаюсь отправить ответ api в действующий веб-узел, в котором участвуют два пользователя. Итак, чтобы реализовать это, как я могу получить имя_канала? Спасибо - person Danny; 14.03.2021
comment
@Danny в этом случае вам нужно либо вести инвентаризацию имен каналов в своей БД, либо создать группу для каждого пользователя с известным идентификатором, уникальным для пользователя (например, это может быть идентификатор пользовательской БД), а затем всякий раз, когда вы хотите чтобы отправить сообщение этому пользователю, вы просто отправляете его группе, чей идентификатор вы можете легко получить из БД. Второй вариант лучше, особенно в тех случаях, когда пользователь может подключаться с нескольких устройств. - person Ken4scholars; 15.03.2021
comment
Спасибо за ответ. Вы хотели создать группу каналов? - person Danny; 15.03.2021
comment
Да, группа каналов - person Ken4scholars; 15.03.2021
comment
@ Ken4scholars, пожалуйста, ответьте на этот вопрос, когда освободитесь? https://stackoverflow.com/questions/66638287/websocket-connection-getting-closed-automatically-when-sending-data-from-an-exte спасибо - person prehistoricbeast; 15.03.2021