О проекте «Биржа Услуг»

Закончил разработку небольшого проекта для тестового задания, и запустил его по адресу 🔗 http://exchange.amgold.ru/. В этом посте хочу рассказать о том, какая стояла задача, какие инструменты были использованы, и что в итоге получилось.

Задача

Тестовое задание выглядело примерно таким образом:

Нужно создать сайт на Flask или Django с панелью администратора и двумя кабинетами пользователя: в роли заказчика и исполнителя. Профиль пользователя должен иметь такие поля, как имя, контактные данные, сведение об опыте. Пользователи должны иметь возможность: размещать свои услуги, или наоборот – информацию о задачах, которые им необходимо выполнить; заказывать услуги, или предлагать выполнить задачи других пользователей. Оформление сайта не принципиально.

Инструменты

В качестве фреймворка я без колебаний выбрал Django, так как в нём "из коробки" есть великолепная админка, мне нравится встроенная ORM, и в целом, на мой взгляд, Django идеально подходит для таких задач.

К Django добавил джентльменский набор – django-allauth для аутентификаци, environs для работы с переменными окружения, django-debug-toolbar незаменим для отладки. Для тестов взял factory-boy и faker: фабрики мне показались более гибким инструментом для тестирования, чем использование фикстур.

Очередь задач реализована при помощи Celery и Redis: в проекте предполагается оплата услуг, поэтому без очереди никуда.

Хотя в задании и было явно указано, что оформление не принципиально, всегда приятнее работать над опрятными страницами. Поэтому для вёрстки я выбрал Tailwind CSS. Этот фреймворк позволяет очень быстро делать аккуратную разметку, не заботясь об описании собственных стилей. Специальная команда, работающая под Node, сканирует указанную директорию с шаблонами, и прописывает в выходном CSS-файле только задействованные стили. Таким образом, ничего лишнего включено не будет, и странички останутся компактными. А плагин для Django под названием crispy-tailwind при помощи фильтра {{ form|crispy }} в шаблоне оформляет поля стилями Tailwind, и придаёт форме аккуратный вид.

Для деплоя я использовал Docker Compose. Ngingx заботится о работе по HTTPS и раздаёт загруженные пользователями файлы из директории /uploads/. Статику отдаёт Django при помощи плагина whitenoise, а работу веб-приложения в целом обеспечивает Gunicorn. Настроил GitHub Actions для CI/CD.

Что было реализовано

  • Регистрация, аутентификация пользователей.
  • Пользователи могут указывать о себе дополнительные сведения – имя, изображение профиля, специальность, навыки, подробности об опыте, и др.
  • В публичном профиле пользователя видна вся информация о нём, а также список его услуг и проектов.
  • Сам пользователь также видит в своём профиле баланс и последние просмотренные услуги и проекты других пользователей.
  • Создание, редактирование, удаление услуг пользователей.
  • Просмотр списка услуг, с разбивкой по категориям, поиск по услугам.
  • Создание, редактирование, удаление проектов пользователей.
  • Просмотр списка услуг, с разбивкой по категориям, поиск по проектам.
  • Страницы со списком услуг, проектов, заказов пользователя.
  • Пользователи могут предлагать свои услуги по выполнению проекта, а заказчик может отклонить или принять предложения.
  • Желающие могут создать заказ на представленную в каталоге услугу. Исполнитель может отклонить заказ, или взяться за его выполнение. С баланса заказчика снимается стоимость работы, которая при подтверждении выполнения заказчиком начисляется исполнителю. Все действия по заказу (создание, изменение статуса, отмена) регистрируются, и видны на странице заказа.
  • Пользователи могут отправлять друг другу сообщения на странице каждого заказа, при желании – прикреплять к сообщениям файлы.
  • Пополнение баланса пользователя при помощи Celery Task.
  • Аккуратная верстка с Tailwind CSS позволяет легко преобразить оформление страниц. Отмечу, что адаптация под мобильные экраны не делалась, но её легко добавить.
  • Конечно же, прекрасная админ-панель Django на месте!
  • Подключен Sentry.
  • Настроен CI/CD на GitHub.

Сейчас сайт с добавленными мной для демонстрации вымышленными пользователями и данными выглядит примерно вот так:

Image Slider

Интересные решения

Мне хотелось, чтобы модель заказа Order в качестве предмета заказа могла ссылаться на услугу Service или проект Project. Чтобы решить эту задачу, поле Order.item реализовано при помощи GenericForeignKey и модели ContentType (см. код).

Аналогичное решение использовано и для чатов. По задумке, чаты в приложении могут быть привязаны к разным сущностям: заказу, проекту, услуге, и т.п. Или могут быть ни к чему не привязаны, если один пользователь просто отправляет сообщение другому. Для этого через поле Chat.topic к чату может быть привязана, по сути, любая модель (см. код). На данный момент, для простоты, реализованы чаты только с привязкой к заказам – но, при желании, функциональность будет легко расширить!

Идеи для дальнейшего развития проекта

Конечно же, прежде, чем двигаться дальше, сначала нужно обеспечить максимальное покрытие тестами! Я сделал только задел, потому что проект имеет характер прототипа, но если развивать его дальше – нужны тесты.

Чтобы я добавил в первую очередь:

  • Система отзывов о выполненной пользователями работе.
  • Полнофункциональные чаты с привязкой не только к заказам, но и к услугам, проектам, предложениям по проектам.
  • Всяческие quality of life improvements.

Подведем итоги

На выполнение проекта потрачено примерно 46 часов работы в течение 11 дней. Результатом в целом я доволен – напрягает только отсутствие полного покрытия кода тестами. С другой стороны, писать уйму тестов для приложения, которое изначально делается в качестве прототипа, вряд ли стоит. В очередной раз я убедился в двух фактах: писать тесты быстрее и эффективнее параллельно с кодом, и в том, что разрабатывать с Django – одно удовольствие!

Отправить сообщение

С помощью формы ниже, вы можете связаться с автором сайта. Пожалуйста, укажите ваш ник в Телеграме или e-mail, чтобы я смог вам ответить!