Django отправляет события через websocket всем клиентам
Я хочу отправлять события (json-строки) через websocket всем клиентам (всем, кто установил соединение через websocket). Мой код:
Я думаю, что asgi и маршрутизация в порядке
asgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'base_app.settings')
django.setup()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
routing.py
from api_producer.consumers import EventWebSocket
websocket_urlpatterns = [
url('ws/start/', EventWebSocket.as_asgi()),
]
Проблемный момент: Некоторая функция генерирует события, и я хочу отправлять эти события клиентам
from api_producer.consumers import EventWebSocket
def event_producer():
my_socket = EventWebSocket()
my_socket.receive("Some_text")
consumers.py
class EventWebSocket(WebsocketConsumer):
def connect(self):
self.channel_name = "CHANNEL_1"
print("ZZZ_")
async_to_sync(self.channel_layer.group_add)("chat", self.channel_name)
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)("chat", self.channel_name)
def receive(self, text_data):
async_to_sync(self.channel_layer.group_send)( # 'EventWebSocket' object has no attribute 'channel_layer
"chat",
{
"type": "chat.message",
"text": text_data,
},
)
def chat_message(self, event):
self.send(text_data=event["text"])
Мои действия: 1 Перейдите на websocketKing и отправьте запрос ws://127.0.0.1:8000/ws/start/. Вывод журнала:
WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37476]
WebSocket HANDSHAKING /ws/start/ [127.0.0.1:37476]
ZZZ_
WebSocket DISCONNECT /ws/start/ [127.0.0.1:37476]
WebSocket DISCONNECT /ws/start/ [127.0.0.1:37476]
2 Запуск функции event_producer()
- I don't see any output (guess because WebSocket DISCONNECT)
Каков правильный способ отправки событий?
Вы должны отправлять события через канальный слой, Вы можете использовать канальные слои вне потребителей следующим образом
from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
def event_producer():
async_to_sync(channel_layer. group_send)("global", {
"type": "global.event",
"text": "foo"
})
В своем потребителе присоединитесь к глобальному каналу, на который производитель событий отправляет события, и добавьте метод, который может быть вызван производителем событий. Вы можете использовать канал "chat"...
class EventWebSocket(WebsocketConsumer):
def connect(self):
...
async_to_sync(self.channel_layer.group_add)("global", self.channel_name)
self.accept()
...
def global_event(self, event):
self.send(text_data=event["text"])