Skip to content

Latest commit

 

History

History
263 lines (183 loc) · 5.83 KB

File metadata and controls

263 lines (183 loc) · 5.83 KB

Project Documentation

Назначение

Проект — базовый шаблон FastAPI-сервиса для быстрого старта backend API. Шаблон уже содержит:

  • FastAPI приложение с фабрикой get_app();
  • конфигурацию через pydantic-settings;
  • health-check endpoints;
  • SQLAlchemy base model;
  • Alembic migrations;
  • pytest тесты;
  • Docker image;
  • Kubernetes Deployment, Service, ConfigMap, Secret.

Архитектура

Точка входа для локального запуска — app/__main__.py. Она запускает Granian с target app.asgi:app.

ASGI target находится в app/asgi.py и вызывает get_app() из app/application.py.

app/application.py отвечает за:

  • создание singleton FastAPI app;
  • подключение CORS middleware;
  • lifespan hook;
  • опциональный запуск миграций при старте;
  • подключение общего router.

Routers собираются в app/routers/__init__.py. Сейчас подключен системный router app/routers/system.py.

Директории

app/                 source code
app/routers/         HTTP routers
migrations/          Alembic config and migration scripts
tests/               pytest tests and fixtures
k8s/                 Kubernetes manifests
scripts/             helper scripts
htmlcov/             generated coverage report

Локальный запуск

Установить зависимости:

uv sync

Запустить сервис:

uv run python -m app

Порт по умолчанию: 8000.

Проверить:

curl http://localhost:8000/health
curl http://localhost:8000/healthz

Конфигурация

Все настройки читаются из env и .env без prefix.

Переменная Назначение Default
SERVICE_NAME имя сервиса, title API, logger name fastapi-service
VERSION версия приложения 0.1.0
ENVIRONMENT окружение development
LOG_LEVEL уровень логирования Granian/app info
HOST bind host 0.0.0.0
PORT bind port 8000
RELOAD Granian reload false
CORS_ORIGINS allowed CORS origins ["*"]
RUN_MIGRATIONS_ON_STARTUP запуск Alembic при старте false
DATABASE_URL DSN БД для app/Alembic null

Пример .env:

SERVICE_NAME=fastapi-service
VERSION=0.1.0
ENVIRONMENT=development
LOG_LEVEL=info
HOST=0.0.0.0
PORT=8000
RELOAD=true
CORS_ORIGINS=["*"]
RUN_MIGRATIONS_ON_STARTUP=false
DATABASE_URL=postgresql+psycopg://user:pass@localhost:5432/service_db

API

GET /health

Health endpoint для liveness/readiness probes.

{"status": "ok"}

GET /healthz

Ping endpoint.

{"message": "pong"}

OpenAPI

  • Swagger UI: /docs
  • ReDoc: /redoc
  • JSON schema: /openapi.json

База данных и миграции

SQLAlchemy declarative base находится в app/db.py.

Новые ORM-модели:

  1. Создать модель в отдельном модуле или рядом с доменом.
  2. Унаследовать от Base.
  3. Импортировать модель в app/models.py.
  4. Создать миграцию:
make migrate-create msg="add_users"

Применить миграции:

make migrate-apply

RUN_MIGRATIONS_ON_STARTUP=true вызывает alembic upgrade head в FastAPI lifespan. Для production предпочтительнее отдельный Kubernetes Job или CI step.

Тестирование

Тесты используют pytest и FastAPI TestClient.

make test

Команда запускает:

uv run --group dev coverage run --source=app -m pytest --ff -vvv
uv run --group dev coverage report --skip-covered
uv run --group dev coverage html

HTML coverage появляется в htmlcov/.

Naming:

  • файлы: tests/test_*.py;
  • функции: test_*;
  • shared fixtures: tests/conftest.py.

Форматирование

make linter

Команда применяет:

  • ruff check --fix .;
  • ruff format ..

Стиль: Python 3.13+, 4 пробела, type hints для публичных функций, snake_case для функций/модулей, PascalCase для классов.

Docker

Собрать image:

docker build -t fastapi-service .

Запустить через Makefile:

make service

Container слушает 8000 и запускает:

python -m app

Kubernetes

Основной manifest: k8s/manifest.yaml.

Он содержит:

  • Secret с DATABASE_URL;
  • ConfigMap с runtime settings;
  • Deployment с liveness/readiness probes;
  • Service типа ClusterIP.

Применить:

kubectl apply -f k8s/manifest.yaml

Перед production заменить demo credentials и image localhost:5000/fastapi-service:latest.

Добавление нового endpoint

  1. Создать router в app/routers/<domain>.py.
  2. Объявить APIRouter.
  3. Подключить router в app/routers/__init__.py.
  4. Добавить тест в tests/.

Пример:

from fastapi import APIRouter

route = APIRouter(prefix="/users", tags=["users"])


@route.get("/")
async def list_users() -> list[dict[str, str]]:
    return []

Перед изменениями в main

Минимальная проверка:

make test
make linter

Для изменений с БД дополнительно:

make migrate-create msg="describe_change"
make migrate-apply