Найти тему
Kangaroo

Синхронизируем websockets и django rest framework

Оглавление

Доброго времени суток читатель!

Я разрабатывал серверную платформу для мобильного приложения. И у меня возникла проблема когда мне нужно было поставить вебсокеты.

Задача была следующей: на определенный url со стороны клиентской части приложения приходит POST запрос, в этот момент в Базу Данных вносятся определенные данные, так же сторона клиента прослушивает другой порт на сервере, по другому протоколу т.е. по протоколу ws. В тот момент когда на сервер приходит запрос по протоколу http необходимо отправить эти данные по протоколу ws.

То что происходит по протоколу http, реализуется с помощью Django rest framework, и запускается на порту 8000(можно поменять). Описывать его работу в статье не буду, у DRF хорошая документация, самый простой код реализации DRF оставлю здесь.

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


На заметку:

Django сам по себе не асинхронный, работает на протоколе http и такая реализация, т.е. протокол ws, на чистой джанге невозможна, для этого джанго-проект нужно с чем то связать.

Теория:
WebSocket - постоянное соединение поверх http(s)
При установлении соединения происходит рукопожатие с помощью специальных http заголовков, после любая сторона в любой момент времени (пока соединение не прервется) может писать в тело запроса сообщения. Каждое такое сообщение представляет из себя передаваемые данные + мета-данные. Более подробно об этом я уже писал в
телеграмм канале

Решение:

Для того чтобы реализовать свой коварный план я использовал Tornado версии 3.2.

Мы будем прослушивать порт 5000 локального хоста по протоколу ws.

Запустим следующий код.

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

Теперь создадим такую функцию которая будет вызывать этот самый метод on_message, отдавая туда те данные, которые нам нужно взять из POST запроса, который нам придет. Эту функцию (т.е. метод connect) мы будем вызывать при серилизации, т.е. в файле serializers.py вашего django-проекта.

Функция принимает два аргумента, data это наш словарь с данными, которые мы будем отправлять по сокетам, второй агрумент не нуждается в объяснении.

Для работы веб сокетов мы использовали следующие пакеты:

sockjs==0.9.1
tornado==3.2
websocket-client==0.56.0

Примеры этого кода я оставлю здесь.

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