Что нового появилось в Django Channels?
С момента последнего поста про Django Channels прошло много времени, проект развивается и потихоньку идёт к стабильному релизу. В новых версиях пакета появляются интересные фишки о которых я сегодня расскажу вкратце:
Generic Consumers
Generic Consumers чем то напоминают Class Based Views в Django. Их задача сократить количество кода при написании обработчиков каналов, а также улучшить их структуру и внешний вид.
Базовым классом является BaseConsumer.
from channels.generic import BaseConsumer
class MyConsumer(BaseConsumer):
method_mapping = {
"your.channel.name": "method_name",
}
def method_name(self, message, **kwargs):
pass
У класса есть атрибут-словарь method_mapping, где ключом является наименование канала, а значением - функция, обрабатывающая данный канал. В случае использования т.н. Class Based Consumers, в настройках роутов нужно прописывать:
from channels import route, route_class
channel_routing = [
route_class(consumers.MyConsumer, path=r"^/myconsumer/"),
]
То есть нужно использовать метод route_class. В последней на данный момент версии (0.17.2), у классов появился метод .as_route()
В пакете также появился WebsocketConsumer, определяющий каркас для работы с WebSocket.
from channels.generic.websockets import WebsocketConsumer
class MyWebsocketConsumer(WebsocketConsumer):
def connection_groups(self, **kwargs):
"""
Возвращает список групп для подключения/удаления подключенных участников
"""
return ['general_group']
def connect(self, message, **kwargs):
"""
Срабатывает при старте соединения по WebSocket
"""
pass
def receive(self, text=None, bytes=None, **kwargs):
"""
Срабатывает, когда приходит сообщение в WebSocket
"""
# Echo
self.send(text=text, bytes=bytes)
def disconnect(self, message, **kwargs):
"""
Срабатывает при разрыве соединения
"""
pass
Если в момент соединения есть необходимость добавлять участника в группу/группы, то переопределите метод connection_groups, и укажите список групп. При разрыве соединения участники будут автоматически удалятся из заданных групп.
Data binding
API data binding ещё до конца не устаканился и поэтому до стабильного релиза может изменяться. Используйте этот функционал аккуратно, и внимательно читайте Changelog при обновлениях django-channels. Главная задача data binding упростить жизнь при обновлениях в моделях Django. Функциональная часть построена на родных Django Signals и имеет ряд ограничений:
- Если вы изменяете объект модели за пределами Django или используете метод .update() на объекте QuerySet, binding не сработает, так как сигнала не произойдёт.
- В качестве сериализаторов моделей используются стандартные средства Django, но при SPA (Single Page Applications) очень часто требуется гибкость в передаваемых данных. Автор советует в таком случае использовать пакет сериализаторов из Django REST Framework.
Подробно с деталями можно почитать тут.
Роутинг с фильтрами
Веб-сокет, например, можно открыть по конкретному URL:
route("websocket.connect", consumers.ws_connect, path=r"^/chat/$")
Нужно фильтровать по входным данным для функции-consumer? Не проблема:
route("email.receive", comment_response, to_address=r".*@example.com$", subject="^reply")
Все именованные аргументы передаются в функцию-consumer, поэтому ловите их там через **kwargs.
Подробнее тут.