Как стать автором
Обновить

Как я пытался подружить Django и Websockets

Время на прочтение2 мин
Количество просмотров16K

Когда браузер клиенту нужно постоянное обновление данных с сервера, на ум сразу приходят сокеты. Но после множества просмотренных мной гайдов по данной теме, я не нашел ничего одновременно и актуального, и с нормальными объяснениями ну или хотя бы работающего. В итоге просидев пару-тройку часов у меня получилось собрать пазл из миллиона статей с Хабра и пары видеороликов от моих коллег из Индии.

Установка

В этой статье я не буду рассказывать как устанавливать 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


class YourConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        await self.send({"type": "websocket.accept"})

    async def websocket_receive(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', 'yourproject.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);
  }
};
Запускаем запрос и видим ответ который мы прописывали в consumers.py
Запускаем запрос и видим ответ который мы прописывали в consumers.py

Ссылки

Документация

Гитхаб

Мой тг

Теги:
Хабы:
Всего голосов 4: ↑2 и ↓2+1
Комментарии9

Публикации

Истории

Работа

Data Scientist
94 вакансии
Python разработчик
193 вакансии

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн