Как стать автором
Обновить
Selectel
IT-инфраструктура для бизнеса

Как разработать канбан-доску на Django, DRF и Alpine.js

Уровень сложностиПростой
Время на прочтение8 мин
Количество просмотров12K

Для структурирования и мониторинга рабочих процессов используют канбан-доски — например, Jira и Trello. Они особенно полезны, когда задачи состоят из множества этапов — согласования, выполнения, ревью и продакшена.

В статье рассказываем, как разработать собственную канбан-доску и развернуть ее на облачном сервере. Подробности под катом.

Текст подготовила Наталья Кайда, технический писатель Proglib. Спасибо!

С чего начнем


Мы разработаем и запустим онлайн-версию классической канбан-доски с четырьмя колонками, которые соответствуют различным стадиям выполнения задач. Карточки можно перетаскивать из одной колонки в другую, редактировать и удалять без перезагрузки страницы.

Канбан максимально использует функциональность Django — управление базой данных, формы, шаблоны, систему аутентификации и авторизации. Асинхронная передача данных и CRUD без перезагрузки доски реализованы с помощью API на Django REST Framework. Фронтенд канбана написан на Alpine.js — это минималистичный JS-фреймворк, который по синтаксису очень похож на Vue.js, а по функциональности на jQuery. Дизайн сделан на CSS-фреймворке Tailwind, а для HTTP-запросов к бэкенду используется библиотека Axios. Весь код для проекта находится в репозитории Kanban.

Бэкенд и API


Модель базы данных board/models.py


Поскольку в канбане фиксированное число колонок, можно обойтись одной моделью Task с полем models.TextChoices. Если нужно дать пользователям возможность создавать неограниченное количество колонок с произвольными именами (как в Trello), потребуется модель Board, с которой модель Task будет связана при помощи ForeignKey. Сериализатор в этом случае будет вложенным.

Представления board/views.py


Декоратор @login_required обеспечивает перенаправление на страницу входа/регистрации для неавторизованных посетителей. Функция def home(request) передает в шаблон index.html все существующие записи пользователя в удобном формате для сортировки задач по статусам.Вся функциональность, связанная с регистрацией, авторизацией и выходом, реализована средствами Django и дополнительного модуля для управления формами django-crispy-forms. Crispy Forms обеспечивают автоматическую валидацию данных. Дизайн для форм предоставляет модуль crispy-tailwind.

API


Реализация API на Django REST Framework выглядит максимально просто и лаконично:

  • Сериализаторы обеспечивают преобразование информации из нужных полей базы данных для использования на фронтенде и конвертируют получаемые с фронтенда данные для записи в базу.
  • Универсальные представления на основе классов ListTask и DetailTask предоставляют всю необходимую CRUD функциональность — создание, редактирование и удаление записей.
  • Фильтр owner=user в get_queryset(self) предоставляет пользователям доступ только к своим собственным записям.
  • Схемы SessionAuthentication и IsAuthenticated гарантируют, что операции с данными по API могут совершать только авторизованные пользователи.

Настройки settings.py


В INSTALLED_APPS необходимо указать формы crispy_forms
и набор стилей для них crispy_tailwind:

INSTALLED_APPS = [

'board.apps.BoardConfig',
'rest_framework',

'api.apps.ApiConfig',

'crispy_forms',

'crispy_tailwind',

]

Фронтенд


Клиентская часть приложения также в значительной мере полагается на встроенные возможности Django и его дополнительных модулей: django-crispy-forms, crispy-tailwind и messages. Фронтенд Канбана состоит из следующих шаблонов:

  • base.html — базовый шаблон с общими настройками для всех остальных страниц. Здесь подключаются Alpine.js, Axios, Tailwind и набор иконок Unicons.
  • index.html — главный шаблон, в котором содержится вся клиентская функциональность приложения.
  • login.html — вход на сайт.
  • messages.html — шаблоны для получения с бэкенда сообщений об успешных (и ошибочных) действиях пользователя.
  • register.html — регистрация на сайте.
  • settings.html — настройки пользовательского интерфейса (цветовая схема и фоновое изображение). Сведения об этих настройках хранятся в localStorage браузера

Шаблон index.html получает данные с бэкенда при загрузке страницы:

const tasksFromDjango = {{ tasks | safe }};

Alpine.js распределяет задачи по соответствующим колонкам:

<template x-for="(t, taskIndex) in tasks.filter(t => t.boardName === board)" :key="taskIndex">

Обращения к API для добавления, удаления и редактирования записей реализованы в addTask, removeTask и updateTask; перемещение задания в другую колонку — в onDrop(event, boardName).


Развертывание приложения на сервере с ОС Ubuntu


Последовательность действий при развертывании готового проекта состоит из следующих шагов:

  • выбор конфигурации сервера, обновление ОС,
  • установка глобальных пакетов и модулей,
  • создание виртуального окружения,
  • клонирование репозитория проекта и установка локального ПО,
  • корректировка settings.py для продакшена,
  • создание базы данных и суперпользователя,
  • связывание Gunicorn с wsgi.py,
  • настройка конфигурации и запуск Gunicorn,
  • настройка и запуск обратного прокси Nginx,
  • получение сертификата Let’s Encrypt.

Рассмотрим эти шаги подробнее.

Конфигурация сервера


В панели управления Selectel откройте раздел «Облачная платформа», выберите «Серверы». Самый оптимальный вариант для развертывания нашего проекта — Shared Line:


Не забудьте выбрать опцию «Новый плавающий IP-адрес»: по этому адресу приложение будет доступно в интернете:


Конфигурация нашего сервера выглядит так:



Обновление ОС и установка глобального ПО


Начинаем работу с обновления Ubuntu и установки нужных пакетов:

sudo apt update

sudo apt install git ufw python3-pip python3-dev nginx

Создание виртуального окружения и клонирование репозитория с GitHub


Установим virtualenv:

sudo -H pip3 install --upgrade pip

sudo -H pip3 install virtualenv

Создадим директорию для проекта:

mkdir myproject

cd myproject

Создадим виртуальное окружение для проекта:

virtualenv myprojectenv

Активируем окружение:

source myprojectenv/bin/activate

В результате в начале командной строки будет отображаться (myprojectenv).

Теперь скопируем файлы проекта из GitHub-репозитория на сервер:

git clone https://github.com/natkaida/kanban.git

Установка Gunicorn и production-настройки

Перейдем в корневую директорию проекта, установим зависимости и Gunicorn:

cd kanban

pip install -r requirements.txt

pip install gunicorn

Создадим файл local_settings.py по этому примеру:

nano kanban/kanban/local_settings.py

Нужно убедиться, что значение DEBUG равно False, и прописать допустимые IP — локальный и внешний, в нашем случае это 95.213.229.177:

ALLOWED_HOSTS = ['95.213.229.177', 'localhost']

Кроме этого, нужно вставить соответствующее значение в SECRET_KEY, например:

SECRET_KEY = '!_u(2(^lpy&-2x$e%!k_u_gir0hg)q&5nurj00*gq0s4sseuav'

Теперь можно создать базу данных, сделать аккаунт администратора и собрать статические файлы в папку static:

python3 manage.py migrate

python3 manage.py createsuperuser

python3 manage.py collectstatic

Назначьте права для папки static:

chown www-data myproject/kanban/static

Добавьте порт 8000 в исключения фаервола:

sudo ufw allow 8000

Теперь можно запустить проект на собственном сервере Django:

python3 manage.py runserver 0.0.0.0:8000 --insecure

Параметр —insecure нужен для того, чтобы Django «увидел» статические файлы в папке static — после переключения статуса DEBUG на False он уже не занимается статикой по умолчанию. В дальнейшем работать со статическими файлами будет другой сервер. Мы установим его чуть позже. После запуска сервера сайт будет доступен по адресу http:// 95.213.229.177:8000:


Для входа в панель администрирования достаточно добавить /admin – http:// 95.213.229.177:8000/admin:


Подключение Gunicorn


Для работы Django-приложения в продакшене необходим надежный WSGI-сервер. В качестве такого сервера мы будем использовать Gunicorn:

cd myproject

gunicorn --bind 0.0.0.0:8000 kanban.wsgi

Перезапустим сервер:

python3 manage.py runserver 0.0.0.0:8000

Сайт должен быть доступен по тому же адресу http:// 95.213.229.177:8000. В случае ошибки проверьте, установлен ли Gunicorn в виртуальное окружение проекта myprojectenv. Если все работает корректно, остановите сервер (Ctrl + C) и деактивируйте виртуальное окружение командой deactivate.

Настройка конфигурации Gunicorn


Пока что нам приходилось запускать и останавливать сервер вручную. Но при наличии соответствующих конфигурационных файлов этот процесс можно полностью автоматизировать.

Нам понадобятся два файла: gunicorn.socket и gunicorn.service. Сначала создадим файл gunicorn.socket:

sudo nano /etc/systemd/system/gunicorn.socket

Его содержимое выглядит так:

[Unit]

Description=gunicorn socket

[Socket]

ListenStream=/run/gunicorn.sock

[Install]

WantedBy=sockets.target

Нажмите Ctrl + X и подтвердите сохранение.

Теперь с помощью команды sudo nano /etc/systemd/system/gunicorn.service создайте файл gunicorn.service:

[Unit]

Description=gunicorn daemon

Requires=gunicorn.socket

After=network.target

[Service]

User=root

WorkingDirectory=/root/myproject/kanban

ExecStart=/root/myproject/myprojectenv/bin/gunicorn --workers 5 --bind unix:/run/gunicorn.sock kanban.wsgi:application

[Install]

WantedBy=multi-user.target

Проверить файл gunicorn.service на наличие ошибок можно этой командой:

systemd-analyze verify gunicorn.service

Если при проверке оказалось, что путь к вашему gunicorn отличается от приведенного выше, то корректный путь к файлу можно найти, если активировать виртуальное окружение и выполнить команду which gunicorn. Если ошибок нет, можно активировать сервер:

sudo systemctl start gunicorn.socket

sudo systemctl enable gunicorn.socket

Проверим статус:

sudo systemctl status gunicorn.socket

Статус корректно настроенного Gunicorn выглядит так:


В случае обнаружения ошибок, после их исправления нужно перезапустить Gunicorn, иначе он будет использовать предыдущую, ошибочную конфигурацию:

systemctl daemon-reload

Настройка Nginx


Перейдем к настройке Nginx. Создайте новый файл kanban без расширения:

sudo nano /etc/nginx/sites-available/kanban

В содержимом файла необходимо указать IP, по которому будет доступен сайт, порт и путь к директории со статическими файлами:

server {

listen 80;

server_name 95.213.229.177;

location = /favicon.ico { alias /myproject/kanban/static/favicon.ico }

location /static {

root /myproject/kanban/static;

}

location / {
include proxy_params;

proxy_pass http://unix:/run/gunicorn.sock;

}

}

Сохраните файл, а затем выполните приведенную ниже команду для создания символической ссылки:

sudo ln -s /etc/nginx/sites-available/kanban /etc/nginx/sites-enabled/

Чтобы проверить файл на наличие ошибок или опечаток, выполните команду:

sudo nginx -t

Если все в порядке, перезапустите Nginx:

sudo systemctl restart nginx

Осталось открыть порт 80:

sudo ufw delete allow 8000

sudo ufw allow 'Nginx Full'

Все готово — сайт доступен по адресу 95.213.229.177:


Сертификат Let’s Encrypt


Для безопасной передачи данных на сайт нужно установить SSL-сертификат. Тогда сайт будет доступен по https. Однако получить сертификат можно лишь при наличии доменного имени. Для установки certbot выполните команду:

sudo apt-get install certbot python3-certbot-nginx

Затем запустите процедуру получения сертификата:

sudo certbot certonly --nginx

На этом этапе потребуется ввести адрес электронной почты и согласиться с условиями предоставления сертификата, после чего необходимо указать доменное имя сайта. Если указать просто IP, процедура прервется:


Заключение


Деплой Django-приложения — непростая задача для начинающего разработчика. Однако процесс развертывания становится интуитивно понятным, если представить себе схему взаимодействия Nginx, Django и Gunicorn: в этой связке Nginx выступает в качестве веб-сервера, обратного прокси-сервера и отвечает за выдачу статического контента, в то время как Gunicorn играет роль сервера приложений и прослойки между Nginx и Django. Nginx не способен запускать веб-приложения на Python и переводить запросы в WSGI, поэтому он передает HTTP-запросы Gunicorn, который, в свою очередь, отправляет их в Django для взаимодействия с ORM базы данных.

При использовании настроек, приведенных в статье, Nginx и Gunicorn будут идеально дополнять друг друга и обеспечат бесперебойную работу высоконагруженного Django-приложения.

Возможно, эти тексты тоже вас заинтересуют:

Недорогие механические клавиатуры: 5 вариантов, на которые стоит обратить внимание в 2023 году
Удар, еще удар: производство ОЗУ переживает не лучшие времена. Цены падают, производство сокращается
Еще есть куда падать: эксперты предрекают обвал поставок ПК на глобальном рынке в 2023 году. Причины и варианты решения
Теги:
Хабы:
Всего голосов 40: ↑36 и ↓4+39
Комментарии8

Публикации

Информация

Сайт
slc.tl
Дата регистрации
Дата основания
Численность
1 001–5 000 человек
Местоположение
Россия
Представитель
Влад Ефименко