раздел 05 · шаг 2/7

Шаг 2. FastAPI + SQLite

Поднимаем бэкенд. SQLAlchemy 2.0 в async-режиме, SQLite как лёгкая БД для локалки, базовый CRUD над задачами. На этом шаге работаем почти исключительно через Claude - он пишет код, мы запускаем.

Что делаем

  • Один большой промпт Claude - получаем готовый бэкенд
  • Запускаем uvicorn, проверяем /docs
  • Через Swagger UI создаём первую задачу
  • Коммитим

Промпт для Claude

Скопируйте этот текст в чат Claude Code (вы должны быть в корне проекта):

Создай FastAPI приложение в backend/ со следующим:

- SQLAlchemy 2.0 + SQLite, async-режим (aiosqlite)
- Модель Task: id (int, PK, autoincrement), title (str, до 200 символов),
  category (str, default "other"), done (bool, default false),
  created_at (datetime, server_default=now())
- Pydantic v2 схемы для запросов/ответов:
  TaskCreate (title), TaskUpdate (title?, category?, done?), TaskRead (все поля)
- CRUD endpoints:
  GET /api/tasks - список, сортировка по created_at desc
  POST /api/tasks - создать (только title в теле)
  PATCH /api/tasks/{id} - частичное обновление
  DELETE /api/tasks/{id} - удалить
- CORS middleware: разрешить http://localhost:5173
- Структура: app/main.py, app/db.py, app/models.py, app/schemas.py, app/routers/tasks.py
- requirements.txt со всеми зависимостями
- Базовый pytest-сетап в tests/ с conftest.py (фикстура async client + тестовая БД in-memory)
- Один smoke-тест: POST /api/tasks с валидным title возвращает 201
- Запиши команды запуска в README.md в корне проекта

Используй современный async-стиль FastAPI: lifespan вместо on_event,
AsyncSession, async def роуты, async фикстуры в pytest.

Что Claude создаст

Структура после генерации:

backend/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI app + lifespan + CORS
│   ├── db.py                # async engine, async session
│   ├── models.py            # Task SQLAlchemy model
│   ├── schemas.py           # TaskCreate, TaskUpdate, TaskRead
│   └── routers/
│       ├── __init__.py
│       └── tasks.py         # CRUD endpoints
├── tests/
│   ├── __init__.py
│   ├── conftest.py          # async client fixture, test DB
│   └── test_tasks.py        # smoke-тест
├── requirements.txt
└── tasks.db                 # появится после первого запуска

requirements.txt будет примерно таким:

fastapi>=0.115
uvicorn[standard]>=0.32
sqlalchemy>=2.0
aiosqlite>=0.20
pydantic>=2.9
pytest>=8.0
pytest-asyncio>=0.24
httpx>=0.27

Устанавливаем зависимости

source venv/bin/activate
cd backend
pip install -r requirements.txt

Запуск

# из папки backend/, venv активен
uvicorn app.main:app --reload --port 8000

В логах должно быть что-то такое:

INFO:     Uvicorn running on http://127.0.0.1:8000
INFO:     Application startup complete.

Проверка

Откройте в браузере: http://localhost:8000/docs

Это автоматический Swagger UI. Через него можно вызвать любой endpoint без curl.

Проверьте создание задачи:

  1. Раскройте POST /api/tasks
  2. Нажмите "Try it out"
  3. В теле: { "title": "купить молоко" }
  4. Execute

Должен вернуться 201 Created и JSON с id, title, category: "other", done: false, created_at.

Затем GET /api/tasks - в ответе массив с одной задачей.

Запуск тестов

cd backend
pytest -v

Должен пройти хотя бы один тест (POST /api/tasks возвращает 201). Если фейлится - копируйте лог в Claude, он поправит.

Возможные проблемы

  • "no module named 'aiosqlite'" - не активировали venv или не сделали pip install
  • "address already in use" - порт 8000 занят. Запустите на другом: --port 8001 (и поправьте фронт потом)
  • pytest падает с "event loop" - в conftest.py должно быть asyncio_mode = "auto"pytest.ini или pyproject.toml)

Точка сохранения

cd ..  # вернуться в корень проекта
git add .
git commit -m "step 2: FastAPI backend with SQLite, CRUD for tasks"

Полезные ссылки