C

cfttt

1. Подготовка и запуск проекта (быстрый старт)

  1. Клонируем проект из репозитория.
  2. Устанавливаем зависимости через pip pip install -r requirments.txt или poetry poetry install .
  3. Настраиваем .env файл с переменными окружения. Данный файл используется только для разработки и тестирования приложения. Публиковать в репозитории его не стоит, а в качестве шаблона можно публиковать файл под названием .example.env. Публикация данного файла в репозитории обуславливается упрощением проверки ТЗ. Данный файл не используется для настройки переменных окружения при разворачивании Docker контейнеров. Пояснение полей файла с переменными окружения описано далее.

DB_HOST - Хост БД, по умолчанию указан localhost.

DB_PORT - Порт БД, по умолчанию PostgreSQL слушает порт 5432.

DB_USER - Пользователь БД, который осуществляет управление и внесение изменений в базу от лица приложения, по умолчанию postgres.

DB_NAME - Имя БД в которой хранятся данные для работы с приложением.

DB_PASS - Пароль пользователя БД.

PASS_SALT - Соль для пароля при регистрации пользователей приложения. Пароли в БД хранятся в хешированном виде. В приложении используется простой механизм соления паролей: одна соль на все пароли.

JWT_SECRET_KEY - Ключ для соления JWT токенов. Одна на все токены.

JWT_ALGORITHM - Алгоритм шифровки токена отпускаемого пользователю.

JWT_ACCESS_TOKEN_EXPIRE_MINUTES - Время актуальности токена в минутах. При истечении срока, токен становится неактуальным и при его предъявлении доступ к ручке будет не доступен.

  1. Настройка приложения на данном этапе завершена. Перейдем к запуску.
  2. Выполним подготовку миграции моделей в БД. Для этих целей в проекте используется alembic. Находясь в корне проекта, выполним команду в терминале alembic revision --autogenerate -m "first_migration". Флаг со значением -m "first_migration" можно опустить, поскольку является только названием миграции. После выполнения данной команды в src/app/migrations/versions появится файл с миграцией, а в БД появится таблица с версиями миграций.
  3. Выполним миграцию моделей в БД. Находясь в корне проекта, выполним команду в терминале alembic upgrade head. После выполнения данной команды, в БД появится таблица: users.
  4. Запускаем приложение. Сделать это можно 2-мя способами: с помощью команды в терминале (находимся в корне проекта) uvicorn src.app.main:app --reload, либо запустив main.py "IDEшным" способом.
  5. Переходим на http://127.0.0.1:8000/docs# и тестируем ручки из документации Swagger.

Механизма хранения токенов не предусмотрено, поэтому для корректной работы следует использовать функционал Swagger. Авторизация проходит через соответствующую кнопку Authorize. Механизм аутентификации и авторизации происходит по протоколу Oauth2.0 с использованием встроенного в fastapi OAuth2PasswordBearer. Механизма logout не предусмотрено (за исключением встроенным в Swagger), поэтому ждем пока токен протухнет или логинимся под другим пользователем.

Механизмы хеширования паролей и создание JWT токенов самые простые. Токен хранит в себе 2 поля: sub - id пользователя из БД, exp - время экспирации токена.

2. Описание и структура проекта

Дерево структуры проекта:

cft-project
├── .venv
├── src
│   ├── app
│   │   ├── migrations
│   │   │   ├── versions
│   │   │   ├── env.py
│   │   │   └── script.by.mako
│   │   ├── models
│   │   │   ├── __init__.py
│   │   │   ├── base.py
│   │   │   └── users.py
│   │   ├── routers
│   │   │   ├── auth.py
│   │   │   └── user.py
│   │   ├── utils
│   │   │   ├── auth.py
│   │   │   └── database.py
│   │   ├── schemas
│   │   │   ├── tokens.py
│   │   │   └── users.py
│   │   └── main.py
│   └── tests
│       └── routers
│           ├── auth.py
│           └── user.py
├── .dockerignore
├── .env
├── .gitignore
├── alembic.ini
├── docker-compose.yml
├── Dockerfile
├── README.markdown
├── poetry.lock
├── pyproject.toml
└── requirments.txt

Данная структура проекта предполагает простое расширение функционала в случае необходимости.

2.1. alembic и миграции

Директория src/app/migrations является инициализируемой директорией alembic, файл env.py служит для настройки подключения к БД (для alembic) и указания моделей sqlalchemy необходимых для создания миграций. В файле имеются строчки:

from src.app.models.base import Base
from src.app.models.users import User

Данные импорты служат указанием моделей необходимых для миграции. Модель Base используется для получения метадаты, а модель User используется для включения таблицы в миграцию. При возможном расширении количества моделей, стоит внести импорты в данный файл, в противном случае, модель не будет включена в миграцию. Параметры для подключения к БД подтягиваются из переменных окружения.

Директория src/app/migrations/versions хранит в себе файлы для прогона миграций.

Файл alembic.ini в корне проекта является конфигурационным файлом, в нем уже настроена директория для необходимых скриптов, шаблон для именования миграций в виде предварительной временной метки осуществления записи миграции, URL для подключения к БД, указана хука использующая black для рефакторинга миграции.

2.2. Модели sqlalchemy

Директория src/app/models служит для работы по созданию и описанию моделей sqlalchemy. В текущем проекте имеется 2 модели: базовая (описана в файле base.py), от которой наследуются все остальные и модель User(описана в файле users.py). В структуре данного проекта предпологается именование файлов и таблиц в множественном числе от названия модели. Модели описаны в декларативном стиле с использованием Mapped и при необходимости mapped_column() для аннотации типов и установки дополнительных параметров и/или ограничений. Рекомендуется переопределение метода __repr__() для упрощения отладки при разработке приложения. Вынесение параметра id в базовую модель не предусмотрено и не рекомендуется для других параметров, хоть это и уменьшает объём кода, это может привести к путанице, а явное в 99.9% случаев лучше неявного.

Данная структура упрощает расширение моделей. Описание новой модели следует проводить в текущей рабочей директории с использованием правил и рекомендаций выше. Для дальнейшего использования модели рекомендуется сделать импорт в файл __init__.py, это очень сильно упростит создание связей relationship(), маппинг на другие модели следует проводить с указанием имени класса заключенного в кавычки. При данном подходе удаётся избежать циклических импортов без использования TYPE_CHECKING (p.s. по крайней мере при текущей версии sqlalchemy). Не забывам про импорт новых моделей в файл env.py из предыдущего пункта о миграциях.

2.3. Схемы pydantic

Директория src/app/schemas служит для работы по созданию и описанию схем pydantic. В текущем проекте имеется 2 семейства схем: описанные в файлах tokens.py и users.py. Каждое семейство рекомендуется описывать в отдельном файле. Именование файла происходит от множественного числа названия сущности, которую описывают данные схемы. Схемы описанные в файлах служат для получения данных от клиента, прохождения валидации полученных данных, обработки данных и их последующий возврат клиенту.

При расширении схем следует использовать правила и рекомендации описанные выше.

2.4. Роутеры fastapi

Директория src/app/routers служит для работы по созданию и описанию роутеров fastapi. В данном проекте имеется 2 роутера: первый для работы с аутентификацией и авторизацией пользователя, второй для работы с операциями над сущностью User. В данном проекте файлы роутеров именуются в единственном числе от названия сущности роутера. Все ручки описываемые в проекте рекомендуется описывать в роутерах. Файл main.py хоть и предоставляет такую возможность, но его следует использовать для более глобальных целей, к примеру для установки ограничений на количество запросов к сервису. Импорт роутеров в main.py осуществляется с использованием алиасов as. Это позволяет использовать единую конструкцию именования переменных роутеров. Для любого роутера название переменной будет router и только в main.py следует разграничить названия. Каждый роутер имеет свой тег и префикс к маршруту.

При расширении роутеров следует использовать правила и рекомендации описанные выше.

2.5. Вспомогательные скрипты и зависимости (Dependencies)

Директория src/app/utils служит для работы по созданию и описанию вспомогательных функций для работы приложения, а так же зависимостей (Depends) для ручек. В данной директории файлы именуются в соответствии со сферой в которой применяются функции, в ед. числе. В данной директории имеется 2 файла database.py - служит для подключения к БД, методом получения асинхронной сессии, и auth.py - в нём описаны функции для создания и обработки токенов и паролей, а так же необходимые зависимости для обработки данных в БД на тему аутентификации и авторизации. При большом количестве вспомогательных функций и зависимостей стоит распределить директорию на src/app/utils/dependencies и src/app/utils/tools.

При расширеннии аналогичных функций следует использовать правила описанные выше.

2.6. Тестирование с pytest

Директория src/test служит для работы по тестированию. За тестирование ручек отвечает директория src/test/routers, каждый файл отвечает за тестирование ручек данного роутера. Файлы именуются аналогично роутерам.

Следует учесть, что тестируются ручки находящиеся в директории src/app/routers а они имеют подключение к БД на основе конфигурационного файла в корне проекта .env, соответственно перед тестированием ручек необходимо изменить конфигурационный файл (если не хотим мучать "рабочую" базу).

При расширеннии тестов следует использовать правила описанные выше.

2.7. Контейнеризация с Docker и использование переменных окружения

Данное приложение подготовлено для контейнеризации в Docker.

Файл Dockerfile описывает контейнер с приложением, работа осуществляется на основе образа python:3.13-slim, далее с помощью pip устанавливается poetry, который в свою очередь устанавливает необходимые зависимости. Далее происходит копирование необходимых рабочих файлов и запуск приложения. Обратите внимание на то, что конфигурационный файл .env не принимает никакого участия в настройке контейнера, поскольку это является нежелательной практикой. О конфиге для приложения ниже.

Файл docker-compose.yml описывает "развертывание" приложения, помимо запуска контейнера с приложением так же будет развернута БД, с которой будет "сотрудничать" приложение. Именно в данном файле осуществляется настройка переменных окружения, используемое для работы приложения:

Секция db:environment:

POSTGRES_USER - Пользователь БД аналогичный 1 пункту.

POSTGRES_PASSWORD - Пароль пользователя БД аналогичный 1 пункту.

POSTGRES_DB - Имя БД аналогичное 1 пункту.

Секция db:healthcheck:test:

Флаг-U - Пользователь БД

Флаг -d - Имя БД.

Секция app:environment:

DB_HOST - Хост БД. Настройки не требует, подтягивается на основе db.

DB_PORT - Порт БД. Используется аналогичное db:ports:.

DB_USER - Пользователь БД. Аналогичное POSTGRES_USER.

DB_NAME - Имя БД. Аналогичное POSTGRES_DB.

DB_PASS - Пароль пользователя БД. Аналогичное POSTGRES_PASSWORD.

PASS_SALT - Соль для хеширования паролей. Алгоритм хеширования паролей простой, используется одна соль для хеширования всех паролей.

JWT_SECRET_KEY - Ключ для кодирования токенов. Алгоритм кодирования простой, используется один ключ для кодирования всех токенов.

JWT_ALGORITHM - Алгоритм кодирования токенов. Так же один для всех.

JWT_ACCESS_TOKEN_EXPIRE_MINUTES - Время актуальности токена.

Для разворачивания контейнеров находясь в корне проекта необходимо выполнить в терминале docker-compose up -d.

По завершению необходимо выполнить миграции docker exec cfttt-app-1 alembic revision --autogenerate -m "init in docker" далее прогон docker exec cfttt-app-1 alembic upgrade head. Приложение готово к работе, документация Swagger доступна на http://127.0.0.1/docs#/