/fastapi_base

Базовый шаблон проекта для FastAPI

Primary LanguagePython

Базовый шаблон проекта для FastAPI

Общее описание

Примеры приведенные ниже, подсказывают как можно организовать структуру проекта FastAPI.

Так же предложен вариант использования паттернов Dependency Injection и Unit of Work. Принцип заключается в том, чтобы разделить логику и код на слои.

Что позволит иметь:

  • более поддерживаемую и понятную структуру проекта
  • масштабирование и переиспользование кода
  • возможность тестирования отдельных частей проекта

О слоях

Контроллеры

Контроллеры мы можем называть по разному: routers, endpoints, controllers.

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

Нужно использовать зависимости (Depends) так как они кешируются. Зависимости можно использовать повторно несколько раз — FastAPI по умолчанию кэширует результат зависимости в пределах области запроса, т.е. если у нас есть зависимость, которая вызывает сервис, мы не будем посещать БД каждый раз, когда вызываем эту зависимость — только первый вызов функции.

Зная это, мы можем легко разделить зависимости на несколько более мелких функций, которые работают в меньшем домене и легче повторно использовать в других маршрутах.

Сервисы

Сервис отвечает за бизнес логику и взаимодействуют с репозиторием.

Если в пределах одной сессии (в нашем случае SqlAlchemy) нужно взаимодействовать с несколькими репозиториями, то следует использовать Unit of Work.

Репозитории

Репозиторий — это коллекция, которая содержит сущности, может фильтровать и возвращать результат обратно, в зависимости от требований нашего приложения. Где и как он хранит эти объекты, является ДЕТАЛЬЮ РЕАЛИЗАЦИИ.

В нашем случае репозиторий может взаимодействовать с базой данных, например Postgres, Redis, MongoDB.

Unit of Work

Если сказать просто, UoW это класс, который объединяет репозитории.

Паттерн Unit of Work помогает упростить работу с различными репозиториями и дает уверенность, что все репозитории будут использовать один и тот же DbContext.

Так же использование паттерна Репозиторий и UoW позволяет создать правильную структуру для развертывания приложения и внедрения DI, которые как минимум помогают в тестировании проекта.

Структура

Приложение (app) - отдельная часть логики проекта. Содержит свои контроллеры, сервисы, репозитории, зависимости, модели, exceptions и т.д.

Пример проекта

Структура проекта, где файлы разбиты по приложениям проекта.

Пример структуры проекта

├── migrations/
├── src
│   ├── config/
│   │   ├── database
│   │   │   ├── db_config.py
│   │   │   └── db_helper.py
│   │   └── project_config.py
│   ├── support # app
│   │   ├── support_controller.py
│   │   ├── support_schema.py
│   │   ├── dependencies.py
│   │   ├── constants.py
│   │   ├── exceptions.py
│   │   ├── support_repository.py
│   │   ├── support_service.py
│   └── user # app
│   ├── routes.py
│   └── main.py
├── tests/
│   ├── users
│   └── support
├── pyproject.toml или requirements.txt
├── .env
├── .gitignore
├── logging.ini
└── alembic.ini

Директории и файлы

  • migrations - директория alembic для миграций
  • migrations/versions - файлы миграций
  • migrations/base.py - файл с импортированными модулями моделей для работы автогенерации миграций
  • migrations/env.py - скрипт alembic для работы миграций
  • src/config - директория для общих настроек
  • src/config/database/db_config.py - настройки базы данных
  • src/config/database/db_helper.py - получение сессии базы данных
  • src/config/project_config.py - настройки для проекта
  • src - верхний уровень приложения, содержит общие маршруты, main.py и все приложения
  • src/main.py - корень проекта, который запускает приложение FastAPI
  • src/routes.py - общие routers для всех приложений проекта
  • src/interfaces - директория для классов интерфейсов
  • src/exceptions (errors) - классы exceptions
  • src/models - классы моделей SqlAlchemy
  • src/models/base_model - базовый класс SqlAlchemy
  • src/schemas - общие классы Pydantic
  • src/schemas/base_schema - класс базовой модели Pydantic, с настройкой для интеграция с ORM (Ранее известный как "ORM Mode"/from_orm)
  • src/repositories - классы репозиториев
  • src/repositories/base_repository - класс базового repository
  • src/repositories/sqlalchemy_repository - класс базового repository для SqlAlchemy
  • src/repositories/uow - реализация Unit of Work для использования нескольких репозиториев в одной сессии SqlAlchemy
  • src/services - базовые классы сервисов
  • src/services/generic_service - класс generic для сервисов
  • src/services/base_service - базовый класс сервиса (CRUD) для взаимодействия с repository
  • tests - тесты проекта
  • .env - переменные окружения
  • .env.example - пример (шаблон) для файла .env
  • pyproject.toml - файл зависимостей для poetry
  • poetry.lock - обеспечить согласованность между текущими установленными зависимостями и теми, которые вы указали в файле pyproject.toml
  • requirements.txt - файл зависимостей для pip

Файлы приложения

  • prefix_repository.py - работа с БД (Postgres, Redis, MongoDB и т.д.)
  • prefix_service.py - специфичная для модуля бизнес-логика
  • prefix_schema.py - pydantic модели
  • routers.py - общие routers для всех контроллеров (endpoints, api) модуля
  • dependencies.py - зависимости для приложения
  • exceptions.py - специфические для модуля исключения
  • constants.py - константы

Соглашения

  • Поддерживаем плоскую структуру
  • Избегаем длинных названий файлов и используем _ (user_service.py)
  • Приложение называем в единственном числе (session, user)
  • Сущности более одной собираются в папки (services, schemas)
  • Поддерживаем цепочку Controller - Service - Repository
  • Sharеd сущности выносим вне контекстов (entities, repositories)