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

rf6-ybnfrqaf-bxx3qv6pezo6e4.png


Для структурирования и мониторинга рабочих процессов используют канбан-доски — например, 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 распределяет задачи по соответствующим колонкам: