Когда браузер клиенту нужно постоянное обновление данных с сервера, на ум сразу приходят сокеты. Но после множества просмотренных мной гайдов по данной теме, я не нашел ничего одновременно и актуального, и с нормальными объяснениями ну или хотя бы работающего. В итоге просидев пару-тройку часов у меня получилось собрать пазл из миллиона статей с Хабра и пары видеороликов от моих коллег из Индии.
Установка
В этой статье я не буду рассказывать как устанавливать Django, создавать модели и классы представлений. Предполагается, что у вас уже есть готовый проект и вы просто хотите впилить в него сокеты.
Python
pip install channels
pip install channels-redis
pip install daphne
Если при установке daphne пип выдает ошибку про C++, то скачиваем BuildTools и во время установки выбираем «Разработка классических приложений на C++». Ребутаем комп и снова запускаем pip install.
Шаг №1
В файл settings.py добавляем загруженные пакеты(Причем исходя из документации — daphne надо добавить обязательно в начало списка):
INSTALLED_APPS = [ 'daphne', 'channels', ... ]
В этом же файле изменяем:
WSGI_APPLICATION = 'yourapp.wsgi.application'
на:
ASGI_APPLICATION = 'yourapp.asgi.application'
Добавляем данные Channel layers в settings.py, конфигурация зависит от того, где у вас стоит Redis, подробнее тут. Для тестов я использовал такой сетап:
CHANNELS_LAYERS = { 'default': { 'BACKEND': 'channels.layers.InMemoryChannelLayer' } }
Шаг №2
Создаем файл consumers.py в директории нашего приложения. Если вы работали с Class Based Views в Django то Consumers вам покажется знакомым.
Создаем свой обработчик:
from channels.consumer import AsyncConsumer YourConsumer(AsyncConsumer): async def websocket_connect(self, event): await self.send({"type": "websocket.accept"}) async def websocket_recieve(self, text_data): await self.send({ "type": "websocket.send", "text": "Hello from Django socket" }) async def websocket_disconnect(self, event): pass
Каждый метод класса YourConsumer отвечает за свой тип запросов через сокеты. Очень похоже на CBV
Шаг №3
Изменяем данные файла asgi.py в корневой директории проекта:
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter from channels.routing import URLRouter from django.core.asgi import get_asgi_application from django.urls import path import os os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'yourapp.settings') from yourapp.consumers import YourConsumer django_asgi_app = get_asgi_application() application = ProtocolTypeRouter({ 'http': django_asgi_app, 'websocket': AuthMiddlewareStack( URLRouter([ path('ws', YourConsumer.as_asgi()) ]) ) })
В URLRouter мы прописываем путь, по которому будет доступен Consumer. Например в данном случае для 127.0.0.1 это — ws://127.0.0.1:8000/ws. Это очень похоже на концепцию urls.py, кстати при желании можно вынести все пути в отдельный файл routers.py и импортировать их потом в корневую директорию.
Тестируем
Запускаем локалку и отправляем запросы к сокету. Например через Js:
const socket = new WebSocket('ws://127.0.0.1:8000/ws'); socket.onopen = function(e) { socket.send(JSON.stringify({ message: 'Hello from Js client' })); }; socket.onmessage = function(event) { try { console.log(event); } catch (e) { console.log('Error:', e.message); } };

Ссылки
ссылка на оригинал статьи https://habr.com/ru/post/700100/
Добавить комментарий