Django channels websocket python

Django: WebSocket`ы и Channels

WebSockets — это технология, которая позволяет открывать сеанс интерактивной связи между браузером пользователя и сервером. С помощью этой технологии пользователь может отправлять сообщения на сервер и получать управляемые событиями ответы, не требуя длительного опроса, то есть без необходимости постоянно проверять сервер на предмет ответа. Подумайте, когда вы отвечаете на электронное письмо в Gmail, и в нижней части экрана вы видите всплывающее предупреждение «1 непрочитанное сообщение от [. ]» от человека, на которого вы только что отвечали. Такая обратная связь в режиме реального времени обусловлена такими технологиями, как WebSockets!

Почему WebSockets?

Веб-сокеты позволяют установить длительное одно-сокетное TCP-соединение (протокол управления передачей) между клиентом и сервером, что позволяет мгновенно распределять двунаправленные полнодуплексные сообщения. Это делается с минимальными издержками, что приводит к соединению с низкой задержкой.

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

Что такое Channels?

Channels — это проект, который использует Django и расширяет его возможности за пределы HTTP — для обработки WebSockets, протоколов чата, IoT-протоколов и многого другого. Он построен на спецификации Python под названием ASGI.

Он делает это, беря ядро Django и размещая под ним полностью асинхронный слой, запуская сам Django в синхронном режиме, но обрабатывая соединения и сокеты асинхронно, и давая вам возможность писать в любом стиле.

Как подключить Channels?

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

Читайте также:  Finding file path java

Установка

  • Сначала создайте и активируйте виртуальную среду (pip или pipenv).
  • Установите Django.
  • Установите Channels и channels-redis в вашем виртуальном окружении, например:
    pip install channels
    pip install channels-redis

Если у вас современный макет проекта Django, например:

- my_proj/ - manage.py - game/ - my_proj/ - __init__.py - settings.py - urls.py

Шаг 1:

Файл: my_proj/my_proj/settings.py

# Добавление Channels в приложения проекта INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'game', 'channels', . . . . # Конфигурация Channels ASGI_APPLICATION = "olympia.routing.application" CHANNEL_LAYERS = < 'default': < 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': < "hosts": [CHANNEL_REDIS_HOST], "symmetric_encryption_keys": [SECRET_KEY], >, >, >

Шаг 2:

Каналы (Channels) предоставляют вам Потребителей (Consumers), богатую абстракцию, которая позволяет вам легко создавать приложения ASGI. Потребители, в частности, делают несколько вещей: структурируют ваш код как серию функций, которые будут вызываться всякий раз, когда происходит событие, вместо того, чтобы заставлять вас писать цикл события.

Потребитель — это класс, методы которого вы можете написать как обычные функции Python (синхронные) или как ожидаемые (асинхронные). Асинхронный код не должен смешиваться с синхронным кодом. Таким образом, есть функции преобразования для преобразования из асинхронного в синхронизацию и обратно. Помните, что части Django синхронны. Потребитель фактически является действующим приложением ASGI.

Итак, следующим шагом пишем my_proj/game/consumer.py .

# Встроенные импорты. import json # Импорты сторонних библиотек. from channels.exceptions import DenyConnection from channels.generic.websocket import AsyncWebsocketConsumer # Импорты Django. from django.core.exceptions import ObjectDoesNotExist from django.contrib.auth.models import AnonymousUser # Локальные импорты. from my_proj.game.models import Game from my_proj.game.utils import get_live_score_for_gameclass LiveScoreConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['game_id'] self.room_group_name = f'Game_' if self.scope['user'] == AnonymousUser(): raise DenyConnection("Такого пользователя не существует") await self.channel_layer.group_add( self.room_group_name, self.channel_name ) # If invalid game id then deny the connection. try: self.game = Game.objects.get(pk=self.room_name) except ObjectDoesNotExist: raise DenyConnection("Неверный ID игры") await self.accept() async def receive(self, text_data): game_city = json.loads(text_data).get('game_city') await self.channel_layer.group_send( self.room_group_name, < 'type': 'live_score', 'game_id': self.room_name, 'game_city': game_city >) async def live_score(self, event): city = event['game_city'] # Вспомогательная функция, получающая счет игры из БД. await self.send(text_data=json.dumps(< 'score': get_live_score_for_game(self.game, city) >)) async def websocket_disconnect(self, message): # Покинуть комнату группы await self.channel_layer.group_discard( self.room_group_name, self.channel_name )

Шаг 3:

Следующим шагом является настройка маршрутизаторов для потребителя. Маршрут, который мы задаем в файлах routing.py , используется веб-интерфейсом для фактического доступа к потребителю.

Как только соединение WebSocket установлено, браузер может отправлять или получать сообщения. Отправленное сообщение достигает маршрутизатора типа протокола, который определяет следующий обработчик маршрутизации на основе его транспортного протокола. Следовательно, вы можете определить маршрутизатор для HTTP и другой для сообщений WebSocket.

from django.urls import path from channels.routing import ProtocolTypeRouter, URLRouter from .consumers import LiveScoreConsumer websockets = URLRouter([ path( "ws/live-score/", LiveScoreConsumer, name="live-score", ), ])
from channels.routing import ProtocolTypeRouter, URLRouter from my_proj.game.routing import websockets application = ProtocolTypeRouter(< "websocket": websockets, >)

Источник

Оцените статью