FastAPI и база данных
См. также: FastAPI · Первая программа на FastAPI · Базы данных в Python · Создание API
FastAPI - маршрут от URL до ответа
В обзоре FastAPI и первой программе заметки хранились в словаре _notes в памяти: перезапустили Uvicorn — список пуст. В реальных проектах данные лежат в базе данных (БД): таблицы на диске, переживают перезапуск сервера.
Здесь — сквозной сценарий: HTTP-запрос → FastAPI → SQLAlchemy → SQLite (или PostgreSQL) → JSON-ответ.
Общие термины (DB-API, драйвер, транзакция, пул) — в главе про базы данных.
Словарь
| Термин | Простыми словами |
|---|---|
| ORM | Object-Relational Mapping: класс Python ↔ таблица в БД |
Сессия (Session) | "Рабочая копия" данных на время запроса: читаете, меняете, commit |
| Миграция | Версионированное изменение схемы (добавили столбец — файл в git) |
commit | Зафиксировать изменения в БД |
rollback | Отменить незакоммиченные изменения при ошибке |
| CRUD | Create, Read, Update, Delete |
| DTO | Объект для JSON (часто Pydantic-модель) |
Стек по слоям
| Слой | Библиотека | Роль |
|---|---|---|
| HTTP, маршруты | FastAPI | URL, коды ответа, Depends |
| Валидация JSON | Pydantic | Проверка тела запроса до SQL |
| Таблицы и SQL | SQLAlchemy 2 | Классы UserRow, запросы |
| Файл/сервер БД | SQLite / PostgreSQL | Хранение |
| Запуск | Uvicorn | ASGI-сервер |
pip install fastapi uvicorn sqlalchemy pydantic
Разбор фрагмента:
- Устанавливаются компоненты HTTP-слоя, ORM и валидации схем.
- Такой набор достаточен для первого CRUD-сервиса с БД на FastAPI.
SQLite — файл app.db рядом с проектом. В продакшене — PostgreSQL и пул соединений (см. Работа с базами данных в Python).
Две модели — таблица и JSON
Таблица (SQLAlchemy)
Код ITЗагрузка примера кода…
| Элемент | Смысл |
|---|---|
__tablename__ | Имя таблицы в SQL |
primary_key=True | Уникальный id строки |
unique=True | Два одинаковых username нельзя |
server_default=func.now() | Время создания ставит СУБД |
Схемы API (Pydantic)
from pydantic import BaseModel, Field
class UserCreate(BaseModel):
username: str
email: str = Field(..., pattern=r"^[^@]+@[^@]+\.[^@]+$")
class UserRead(BaseModel):
id: int
username: str
email: str
model_config = {"from_attributes": True}
from_attributes=True — ответ из ORM: UserRead.model_validate(row).
Подключение и get_db
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
DATABASE_URL = "sqlite:///./app.db"
engine = create_engine(
DATABASE_URL,
connect_args={"check_same_thread": False},
)
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)
def init_db():
Base.metadata.create_all(bind=engine)
Разбор фрагмента:
create_engine(...)создаёт подключение к СУБД поDATABASE_URL.sessionmaker(...)настраивает фабрику сессий для unit-of-work.Base.metadata.create_all(...)создаёт таблицы из ORM-моделей, если их ещё нет.
from fastapi import Depends
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
Разбор фрагмента:
- Функция выдаёт отдельную сессию БД на каждый HTTP-запрос.
yieldпередаёт объект в обработчик, аfinallyгарантирует закрытие.- Такой шаблон предотвращает утечки соединений.
check_same_thread=False — особенность SQLite с FastAPI. Одна сессия на HTTP-запрос, закрытие в finally.
CRUD с разбором шагов
Код ITЗагрузка примера кода…
| Шаг | Действие |
|---|---|
body: UserCreate | Pydantic проверил JSON |
db.add(row) | Пометить строку для INSERT |
db.commit() | Записать на диск |
db.refresh(row) | Подтянуть id, created_at |
Связка с API "Заметки"
После Первая программа на FastAPI замените _notes на таблицу NoteRow и те же Pydantic-модели NoteCreate / NoteOut.
Асинхронный PostgreSQL
Синхронный Session в async def блокирует event loop. Для нагрузки — create_async_engine, AsyncSession, драйвер asyncpg — см. Асинхронность и многопоточность в Python, Работа с базами данных в Python.
Миграции Alembic
pip install alembic
alembic init alembic
alembic revision --autogenerate -m "create users"
alembic upgrade head
Разбор фрагмента:
alembic initсоздаёт инфраструктуру миграций в проекте.revision --autogenerateгенерирует миграцию из изменений ORM-моделей.upgrade headприменяет все миграции до актуальной версии схемы.
create_all() — для первого дня; в команде — только Alembic.
Типичные ошибки
| Ошибка | Последствие | Что делать |
|---|---|---|
| Одна сессия на всё приложение | Гонки | Depends(get_db) |
Забыли commit | Данные пропадают после рестарта | commit() после add |
| N+1 | Много SQL на один HTTP | joinedload / один JOIN |
| Секреты в git | Утечка | DATABASE_URL из .env |
Сравнение с Django
Django — ORM и миграции в комплекте. FastAPI + SQLAlchemy — свобода и чистый JSON API. Выбор: Создание собственного API на Python.
Тестирование
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_create_user():
r = client.post("/users", json={"username": "alice", "email": "a@b.c"})
assert r.status_code == 201
Подробнее: Тестирование на pytest.
Связанные материалы
Практика проектирования схемы
Перед созданием таблиц полезно ответить на три вопроса:
- какие поля обязательны для бизнес-операции;
- какие ограничения должна гарантировать сама БД (
UNIQUE,NOT NULL); - какие индексы нужны для частых запросов.
Пример для users:
usernameиemailделают уникальными;created_atхранит момент создания на стороне СУБД;- поиск по
usernameполучает индекс, если это частый кейс.
Такой подход снижает количество ошибок, которые сложно поймать только на уровне API.
Чек-лист перед продакшеном
- строка подключения берётся из переменных окружения;
- миграции Alembic применяются в CI/CD, а не вручную на сервере;
- есть сценарий отката миграции (
alembic downgrade); - для PostgreSQL настроен пул соединений;
- API-тесты покрывают CRUD и конфликт уникальности.
Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.