Создание REST API с FastAPI и MongoDB
Что такое FastAPI?
FastAPI — это современный, высокопроизводительный фреймворк на Python для создания API. Коротко:
- Асинхронная обработка запросов через asyncio.
- Валидация и сериализация входных и выходных данных с помощью Pydantic.
- Автоматическая документация в виде Swagger UI и ReDoc.
Преимущества FastAPI по сравнению с другими инструментами
- Быстрее в обработке конкурирующих запросов благодаря async/await.
- Меньше шаблонного кода: Pydantic упрощает валидацию.
- Автогенерация документации экономит время на тестирование и интеграцию.
Важно: FastAPI — не панацея. Для монолитных проектов с большим количеством готовых модулей возможно лучше подойдёт Django. Выбор зависит от требований по производительности, экосистемы и команды.
Подготовка MongoDB
Вы можете использовать локальную инсталляцию MongoDB или кластер в облаке (Atlas, MongoDB Cloud). Для удобства используйте MongoDB Compass — графический клиент для создания подключений и просмотра коллекций.
Шаги:
- Установите MongoDB или создайте кластер в облаке.
- Откройте Compass и нажмите «New Connection». Вставьте URI подключения (‘mongodb://localhost:27017’ или URI облака).
- Создайте базу данных и коллекцию для тестовых данных.
Создание FastAPI-сервера
В терминале создайте папку проекта и перейдите в неё. Проверка версии Python:
python --versionРекомендуется Python 3.8+.
Создайте изолированное виртуальное окружение и активируйте его. Это уменьшит конфликты зависимостей.
pip install virtualenv
virtualenv venvАктивация:
# На Unix / macOS:
source venv/bin/activate
# На Windows (PowerShell):
.\\venv\\Scripts\\Activate.ps1Установите необходимые пакеты:
pip install fastapi pymongo uvicorn- pymongo — официальный драйвер MongoDB для Python.
- uvicorn — ASGI-сервер для запуска FastAPI (поддерживает hot reload при разработке).
Простейший сервер
Создайте файл server.py в корне проекта и добавьте:
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def home():
return {'message': 'Hello World'}Запустите сервер разработчика:
uvicorn server:app --reloadОткройте http://localhost:8000 — вы увидите ответ и автоматически сгенерированную документацию по адресу http://localhost:8000/docs.
Структура проекта для CRUD API
Рекомендуемая минимальная структура:
├── config
├── models
├── routes
├── schemas
└── server.pyЭта структура разделяет конфигурацию, модели данных, маршруты и схемы сериализации.
1. Конфигурация подключения к БД
В папке config создайте db.py:
from pymongo import MongoClient
# Пример локального URI; для продакшена используйте переменные окружения
client = MongoClient('mongodb://localhost:27017')
db = client['database_name']
collection = db['collection_name']Совет: храните URI в переменных окружения и используйте python-dotenv или встроенный модуль os для чтения.
2. Модель данных (Pydantic)
В models/user_model.py:
from pydantic import BaseModel
class User(BaseModel):
name: str
role: strPydantic автоматически валидирует входные данные и делает сериализацию простейшей.
3. Схема сериализации для MongoDB
MongoDB возвращает BSON ObjectId в поле ‘_id’. Его нужно преобразовать в строку при выдаче через API.
В schemas/user_schema.py:
def user_serializer(user) -> dict:
return {
'id': str(user['_id']),
'name': user['name'],
'role': user['role']
}
def users_serializer(users) -> list:
return [user_serializer(user) for user in users]Объяснение: serializer преобразует объект MongoDB в JSON-дружественный словарь.
4. Маршруты (CRUD)
В routes/user_routes.py создайте маршруты:
from fastapi import APIRouter
from models.user_model import User
from schemas.user_schema import users_serializer
from bson import ObjectId
from config.db import collection
user = APIRouter()
@user.post('/')
async def create_user(user: User):
_id = collection.insert_one(dict(user))
user_data = users_serializer(collection.find({'_id': _id.inserted_id}))
return {'status': 'Ok', 'data': user_data}Инициализация маршрутов в server.py:
from routes.user_routes import user
app.include_router(user)Проверьте POST-эндпоинт через Swagger UI.
Чтение данных (GET)
@user.get('/')
async def find_all_users():
users = users_serializer(collection.find())
return {'status': 'Ok', 'data': users}
@user.get('/{id}')
async def get_one_user(id: str):
user = users_serializer(collection.find({'_id': ObjectId(id)}))
return {'status': 'Ok', 'data': user}Обновление (PUT)
@user.put('/{id}')
async def update_user(id: str, user: User):
collection.find_one_and_update(
{'_id': ObjectId(id)},
{'$set': dict(user)}
)
user_data = users_serializer(collection.find({'_id': ObjectId(id)}))
return {'status': 'Ok', 'data': user_data}Удаление (DELETE)
@user.delete('/{id}')
async def delete_user(id: str):
collection.find_one_and_delete({'_id': ObjectId(id)})
return {'status': 'Ok', 'data': []}Примечание: при удалении часто принято возвращать код 204 No Content. Здесь для простоты возвращается объект с пустым массивом.
Полезные улучшения и лучшие практики
Ниже — список практик, которые полезно внедрить, когда прототип превращается в реальное приложение.
Валидация, обработка ошибок и коды ответов
- Явно возвращайте HTTP-коды: 201 при создании, 404 при ненайденном ресурсе, 400 при неверном запросе.
- Обработчики исключений: используйте exception handlers в FastAPI для унификации ошибок.
- Валидация Pydantic: добавьте ограничения (min_length, regex, enum) в модели.
Пример возврата 404:
from fastapi import HTTPException
@user.get('/{id}')
async def get_one_user(id: str):
result = collection.find_one({'_id': ObjectId(id)})
if not result:
raise HTTPException(status_code=404, detail='User not found')
return {'status': 'Ok', 'data': user_serializer(result)}CORS и безопасность
- Для фронтенда включите CORS через fastapi.middleware.cors.CORSMiddleware только для доверенных источников.
- Не храните секреты в репозитории. Используйте переменные окружения или секрет-менеджер.
- Ограничьте привилегии БД: создайте пользователя MongoDB с минимальным набором прав.
Пример включения CORS:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=['https://your.frontend.domain'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*']
)Производительность и индексы
- Используйте индексы MongoDB для полей, по которым выполняются частые запросы (поиск, сортировка).
- Для тяжёлых операций используйте фоновые задачи (BackgroundTasks) или очереди.
- Горизонтальное масштабирование: выносите ресурсозатратные операции в отдельные сервисы.
Пагинация и фильтрация
Для коллекций используйте пагинацию (skip/limit или курсоры) и параметры фильтрации в запросах, чтобы избежать возврата огромных массивов данных.
Пример простейшей пагинации:
@user.get('/')
async def find_all_users(skip: int = 0, limit: int = 20):
users = users_serializer(collection.find().skip(skip).limit(limit))
return {'status': 'Ok', 'data': users}Логирование и мониторинг
- Логируйте ключевые события (создание, обновление, удаление) и ошибки.
- Подключите мониторинг (Prometheus / OpenTelemetry) для оценки задержек и ошибок.
Тестирование
- Пишите тесты на уровне маршрутов с использованием TestClient из fastapi.testclient.
- Покрывайте позитивные и негативные сценарии.
Пример теста с TestClient:
from fastapi.testclient import TestClient
from server import app
client = TestClient(app)
def test_home():
response = client.get('/')
assert response.status_code == 200
assert response.json()['message'] == 'Hello World'Развёртывание: Docker и процесс
Пример простого Dockerfile для FastAPI:
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
CMD [ 'uvicorn', 'server:app', '--host', '0.0.0.0', '--port', '8000' ]docker-compose.yml (пример с MongoDB):
version: '3.8'
services:
db:
image: mongo:6
restart: unless-stopped
volumes:
- mongo_data:/data/db
ports:
- '27017:27017'
api:
build: .
ports:
- '8000:8000'
depends_on:
- db
volumes:
mongo_data:Важно: в продакшне запускайте Uvicorn вместе с Gunicorn или в режиме нескольких воркеров для устойчивости.
Частые ошибки и отладка
- Проблема: при запросе по id возвращается 500. Причина: неправильный формат ObjectId. Решение: валидировать id и обрабатывать исключения.
- Проблема: CORS блокирует запросы. Решение: проверьте allow_origins и заголовки.
- Проблема: сериализация ObjectId. Решение: всегда преобразуйте ObjectId в str перед отправкой клиенту.
Критерии приёмки
- Все CRUD-эндпоинты корректно работают через Swagger UI.
- При ошибке возвращается информативный статус-код и сообщение.
- Сервер корректно обрабатывает невалидные входные данные (Pydantic).
- Тесты покрывают основные сценарии (create/read/update/delete).
Чек-лист для ролей
Для разработчика:
- Писать типизированный код (Pydantic).
- Добавить обработчики ошибок.
- Написать unit/integration тесты.
Для DevOps:
- Настроить переменные окружения и секреты.
- Настроить сбор логов и мониторинг.
- Настроить контейнеризацию и CI/CD.
Для QA:
- Проверить позитивные и негативные сценарии через Swagger/Postman.
- Проверить пагинацию и фильтрацию.
Мини-методология разработки API
- Спроектируйте модель данных и обязательные поля.
- Напишите Pydantic-модели и схемы сериализации.
- Реализуйте маршруты с минимальной валидацией.
- Добавьте обработку ошибок и тесты.
- Разворачивайте в staging, проверяйте мониторинг и безопасность.
Небольшая галерея крайних случаев
- Очень большой документ: используйте проекцию полей и пагинацию.
- Конкурирующие обновления: рассматривайте оптимистичную блокировку или применяйте операции MongoDB atomic update.
- Требования к транзакциям: MongoDB поддерживает транзакции для репликсет/кластеров; оцените сложность.
Краткий глоссарий
- CRUD — Create, Read, Update, Delete.
- Pydantic — библиотека валидации и сериализации на Python.
- ObjectId — уникальный идентификатор MongoDB.
- Uvicorn — ASGI-сервер для запуска FastAPI.
Резюме
FastAPI позволяет быстро и безопасно создать REST API с минимальным количеством шаблонного кода. Комбинация FastAPI и MongoDB удобна для CRUD-приложений: Pydantic решает большинство задач валидации, а MongoDB обеспечивает гибкую схему данных. Следуйте практикам безопасности, добавляйте индексы и тесты, и вы получите надёжный сервис, готовый к продакшну.
Вам пригодятся: документация FastAPI, документация PyMongo и официальные руководства по развёртыванию MongoDB.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone