Пилим веб-опросник как у Meduza: пошаговый гайд для начинающих
Есть простой способ создавать веб-опросники как в Meduza — такие же красивые и удобные. Разработчик Leader-ID по шагам объясняет, как показывать статистику, подсчитывать баллы, выдавать комментарии, выгружать данные и делиться результатами.
Спустя час разглядывания кирпичной кладки (залипательное занятие, однако) появился первый результат в виде готовых моделей, которые спустя десять минут были описаны в Джанге.
Итак, в проекте я использовал:
- Django 3.0.3. Для бэкенда;
- django-rest-framework. Для создания rest-api;
- Python;
- PostgreSQL в качестве БД;
- Front-end — Nuxt.js, Axios, Element-UI.
Теперь по шагам
pip install Django — устанавливаем библиотеку.
django-admin startproject core — создаем проект на джанге.
cd core — переходим в директорию с проектом.
python manage.py startapp polls — добавляем приложение опроса.
Далее описываем модели в models.py в polls и создаем сериалайзер для DRF.
Затем пишем две вьюшки DRF в views.py, которые отдают все вопросы с вариантами и принимают все ответы от пользователя.
Теперь описываем ссылки в urls.py:
Добавляем модели в admin.py:
Следующим шагом добавляем в settings.py (в директории core) в INSTALLED_APPS наше приложение polls. И выполняем команды запуска:
- python manage.py makemigrations — создаем миграцию для созданных моделей
- python manage.py migrate — выполняем миграцию в БД
- python manage.py createsuperuser — создаем суперюзера (админа)
- python manage.py runserver — запускаем сервер
Чтобы рассчитать общий балл по вопросам, добавляем к методу простенькую функцию обсчета, по которой рассчитывается начисление баллов. Код функции я не выложу, потому что с ее помощью можно взломать наш опросник. Теперь у каждого ответа есть свой «вес».
Заходим в админку через браузер по ссылке, которая указана в консоли (http://127.0.0.1:8000/admin по умолчанию), и создаем вопросы и ответы к ним, проставляем баллы.
Мне было важно отдавать нашим партнерам списки людей, прошедших опрос, и их ответы. Но для этого недостаточно просто связать ответы с вопросами. Поэтому я добавил еще одну таблицу — «Варианты». Так образовалась связь между ответами юзера на вопросы с несколькими вариантами ответов. Это позволяет нам выгружать данные в том виде, в котором партнеры могут их легко интерпретировать.
В итоге структура БД получилась вот такой:
Теперь подключаем фронт.
В нем забираем список вопросов и ответов, проходимся по каждому элементу до последнего. В зависимости от типа вопроса меняем компонент со своей логикой и стилем. Соответственно, когда вопросов в списке не осталось, отправляем результат на бэк и получаем ответ с количеством баллов. После получения количества баллов открываем страницу результата, в случае наличия баллов вопросы более не показываем.
На данном этапе у нас уже готов опросник, который умеет все, что должен: задавать вопросы, получать и собирать варианты ответов, выдавать результат в виде баллов и комментариев.
Добавляем плюшки
Во-первых, мне было необходимо периодически выгружать данные. Для этого я просто добавил management command.
Во-вторых, хорошо бы еще реализовать шаринг результатов опроса в социальные сети. ОК. Пилим функционал, который позволит поделиться картинкой с баллами ВКонтакте и Facebook.
Генерим сто вариантов картинок, отражающих баллы, для ВК и Facebook отдельно (разные разрешения). Теперь подключаем передачу ссылки на картинку в социальном компоненте фронтенд части. С ВКонтаке все оказалось просто: передаем параметр image с прямым URL-адресом нужной. А вот с Facebook пришлось повозиться. Оказалось, что они не принимают медиа по API, и если я передавал image или picture с URL картинки, то в посте показывалось большое пустое поле. Как потом оказалось, берет он картинку из метаинфы (og:image) самого сайта, которым поделились (передаем в ссылке параметр u). А ее, ко всему прочему, нужно было динамично менять. Мне не хотелось делать лишних редиректов и механик на бэке, и я решил переделать SPA (single page app) на SSR (server-side render) на фронте, чтобы в зависимости от запроса менялся url картинки с баллом в head-meta до запуска JavaScript в браузере. Благо, взятый за основу фреймворк Nuxt.js позволяет сделать это простым переключением режима. Теперь осталось набросать client-only теги и добавить логику смены head от наличия query балла.
Дополнительно на сервере понадобилось запустить daemon сервис, чтобы отдавать сформированные страницы, а статику оставить так же nginxу. Все, профит!
Оживляем опросник
Для того, чтобы поддерживать уровень интереса участников в процессе заполнения опроса, я добавил динамический показ статистики к каждому отдельному вопросу. Ответив на вопрос, пользователь видит, как ответили другие. Иногда человеку бывает непонятно, зачем ему задают эти вопросы. Поэтому я дополнил каждый вопрос забавными пояснениями. Ну и самый главный трюк по оживлению моего опросника провернули дизайнеры нашей компании.
Итоги
Такие медийные опросы достаточно просты в реализации и, главное, они очень нравятся пользователям. Их можно использовать и в хвост и в гриву: для социологических исследований, информирования/проверки знаний или создания интерактивных элементов на сайтах и сервисах. Я постарался подробно описать процесс их создания, но если остались вопросы, welcome в комментарии. Примеры реализации опросов на этом движке можно посмотреть по этим двум ссылкам: healthcare.leader-id.ru и covid.leader-id.ru.
- Построение графов для чайников: пошаговый гайд
- Создаем структуру простого мультиплатформенного бота
- Разработка UI: кого слушать — себя или пользователя?
- Реализация алгоритмической теории игр на Python с Nashpy
- Дрон для любителя: устройство и принципы программирования
- Тапочки для гика: ищем позитив во временных закрытиях офисов
- Шутер на миллион с нуля: путь инди-разработчика
- Скучаем по офису. Исповедь команды, привыкшей работать удаленно
- Pylint: детальная проверка работы анализатора кода


