Привет! Одна из лучших фишек FastAPI — автоматическая документация. Она создаётся на основе вашего кода: аннотаций, Pydantic моделей, описаний. Это экономит время и делает API удобным для разработчиков.
В этой статье мы разберём:
- Swagger UI и ReDoc
- Аннотации и описания эндпоинтов
- Настройку документации
- Примеры запросов и ответов
- Кастомизацию
- Что нужно знать перед началом
- Основная часть
- Что такое Swagger UI и ReDoc
- Базовые аннотации
- Описание эндпоинтов
- Pydantic модели в документации
- Примеры запросов и ответов
- Теги для группировки
- Кастомное описание приложения
- Примеры ответов с разными статусами
- Кастомизация OpenAPI
- Полный пример
- Задачи для закрепления
- Нюансы и подводные камни
- Документация доступна только в режиме разработки
- Обновление документации
- OpenAPI версия
- Частые ошибки и как их избежать
- Ошибка 1: Неправильное описание параметров
- Ошибка 2: Отсутствие response_model
- Ошибка 3: Неполное описание статусов
- Шпаргалка
- Заключение
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный FastAPI и Uvicorn
- Базовое понимание эндпоинтов и Pydantic
Совет: Документация FastAPI доступна по адресам
/docs(Swagger) и/redoc(ReDoc).
Основная часть
Что такое Swagger UI и ReDoc
Swagger UI — интерактивная документация, где можно тестировать эндпоинты прямо в браузере.
ReDoc — альтернативная документация с более чистым дизайном.
# Swagger UI
http://localhost:8000/docs
# ReDoc
http://localhost:8000/redocСовет: Swagger UI удобен для тестирования, ReDoc — для чтения.
Базовые аннотации
FastAPI автоматически генерирует документацию из аннотаций.
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
def get_user(user_id: int):
"""
Получить пользователя по ID.
"""
return {"user_id": user_id}Совет: Докстринги добавляют описание в документацию.
Описание эндпоинтов
from fastapi import FastAPI, Query, Path, Body
app = FastAPI()
@app.get("/items/{item_id}")
def get_item(
item_id: int = Path(..., description="ID товара"),
q: str = Query(None, description="Поисковый запрос"),
limit: int = Query(10, description="Лимит результатов")
):
"""
Получить товар по ID с поиском.
"""
return {"item_id": item_id, "q": q, "limit": limit}Совет: Используй
descriptionдля пояснения параметров.
Pydantic модели в документации
Pydantic модели автоматически отображаются в документации.
from pydantic import BaseModel, Field
class UserCreate(BaseModel):
name: str = Field(..., description="Имя пользователя", min_length=2, max_length=50)
email: str = Field(..., description="Email пользователя")
age: int = Field(..., description="Возраст", ge=0, le=120)
@app.post("/users")
def create_user(user: UserCreate):
"""
Создать нового пользователя.
"""
return {"user": user}Совет:
Fieldдобавляет описание и валидацию.
Примеры запросов и ответов
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
class UserResponse(BaseModel):
id: int
name: str
email: str
class UserCreate(BaseModel):
name: str
email: str
@app.post(
"/users",
response_model=UserResponse,
status_code=status.HTTP_201_CREATED,
description="Создание нового пользователя",
summary="Create user"
)
def create_user(user: UserCreate):
"""
**Создаёт нового пользователя.**
- **name**: Имя пользователя
- **email**: Email пользователя
Возвращает созданного пользователя с ID.
"""
return {"id": 1, "name": user.name, "email": user.email}Совет:
summaryдобавляет краткое описание,description— полное.
Теги для группировки
app = FastAPI()
@app.get("/users", tags=["users"])
def get_users():
"""Получить всех пользователей."""
return [{"id": 1, "name": "Анна"}]
@app.get("/posts", tags=["posts"])
def get_posts():
"""Получить все посты."""
return [{"id": 1, "title": "Пост"}]Совет: Теги группируют эндпоинты в документации.
Кастомное описание приложения
from fastapi import FastAPI
app = FastAPI(
title="Мой API",
description="API для управления пользователями и постами.",
version="1.0.0",
contact={
"name": "Имя автора",
"email": "author@example.com",
},
license_info={
"name": "MIT",
"url": "https://opensource.org/licenses/MIT",
},
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json"
)
@app.get("/")
def root():
return {"message": "Добро пожаловать!"}Совет:
contactиlicense_infoдобавляют контактную информацию.
Примеры ответов с разными статусами
from fastapi import FastAPI, HTTPException, status
app = FastAPI()
@app.get(
"/users/{user_id}",
responses={
200: {"description": "Пользователь найден"},
404: {"description": "Пользователь не найден"},
422: {"description": "Ошибка валидации"}
}
)
def get_user(user_id: int):
if user_id == 0:
raise HTTPException(status_code=404, detail="User not found")
return {"id": user_id, "name": f"User {user_id}"}Совет: Указывай все возможные статусы для лучшей документации.
Кастомизация OpenAPI
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Кастомный API",
version="1.0.0",
description="Кастомное описание",
routes=app.routes,
)
openapi_schema["info"]["x-logo"] = {
"url": "https://example.com/logo.png"
}
app.openapi_schema = openapi_schema
return app.openapi_schema
app = FastAPI()
app.openapi = custom_openapi
@app.get("/")
def root():
return {"message": "Hello, World!"}Совет: Кастомизация OpenAPI позволяет добавлять логотипы и другие метаданные.
Полный пример
from fastapi import FastAPI, Query, Path, Body, HTTPException, status
from pydantic import BaseModel, Field
from typing import Optional
app = FastAPI(
title="Blog API",
description="API для управления блогом",
version="1.0.0",
contact={"name": "Admin", "email": "admin@example.com"},
docs_url="/docs",
redoc_url="/redoc"
)
class PostCreate(BaseModel):
title: str = Field(..., min_length=1, max_length=200, description="Заголовок поста")
content: Optional[str] = Field(None, description="Содержимое")
published: bool = Field(False, description="Опубликован?")
class PostResponse(BaseModel):
id: int
title: str
content: Optional[str]
published: bool
@app.get(
"/posts",
response_model=list[PostResponse],
tags=["posts"],
description="Получить список всех постов",
responses={200: {"description": "Список постов"}}
)
def get_posts():
"""Возвращает список всех постов."""
return [
{"id": 1, "title": "Post 1", "content": "Content", "published": True}
]
@app.get(
"/posts/{post_id}",
response_model=PostResponse,
tags=["posts"],
description="Получить пост по ID",
responses={
200: {"description": "Пост найден"},
404: {"description": "Пост не найден"}
}
)
def get_post(
post_id: int = Path(..., description="ID поста", ge=1)
):
"""
Получить пост по ID.
- **post_id**: ID поста (целое число)
"""
if post_id == 1:
return {"id": 1, "title": "Post 1", "content": "Content", "published": True}
raise HTTPException(status_code=404, detail="Post not found")
@app.post(
"/posts",
response_model=PostResponse,
status_code=status.HTTP_201_CREATED,
tags=["posts"],
summary="Create a new post",
description="Создаёт новый пост"
)
def create_post(post: PostCreate):
"""
Создаёт новый пост.
- **title**: Заголовок
- **content**: Содержимое
- **published**: Опубликован или нет
"""
return {"id": 2, "title": post.title, "content": post.content, "published": post.published}Задачи для закрепления
Задача 1. Добавь описание к эндпоинту /users.
Задача 2. Добавь теги для группировки эндпоинтов.
Задача 3. Добавь примеры ответов для разных статусов.
Задача 4. Кастомизируй название и описание приложения.
Задача 5. Настрой документацию с помощью Field.
Ответы:
Задача 1.
@app.get("/users")
def get_users():
"""Получить список всех пользователей."""
return []Задача 2.
@app.get("/users", tags=["users"])
def get_users():
return []
@app.get("/posts", tags=["posts"])
def get_posts():
return []Задача 3.
@app.get("/users/{user_id}", responses={200: {"description": "OK"}, 404: {"description": "Not Found"}})
def get_user(user_id: int):
if user_id == 0:
raise HTTPException(status_code=404)
return {"id": user_id}Задача 4.
app = FastAPI(
title="My API",
description="My API description",
version="1.0.0"
)Задача 5.
class User(BaseModel):
name: str = Field(..., description="Имя пользователя")Нюансы и подводные камни
Документация доступна только в режиме разработки
В продакшене может быть отключена для безопасности.
Обновление документации
Документация обновляется автоматически при изменении кода.
OpenAPI версия
FastAPI использует OpenAPI 3.0.
Частые ошибки и как их избежать
Ошибка 1: Неправильное описание параметров
Используй Path, Query, Body для описания.
Ошибка 2: Отсутствие response_model
Указывай response_model для документирования ответа.
Ошибка 3: Неполное описание статусов
Добавляй все возможные статусы в responses.
Шпаргалка
| Что нужно | Как пишется |
|---|---|
| Swagger UI | /docs |
| ReDoc | /redoc |
| Описание эндпоинта | description="..." |
| Краткое описание | summary="..." |
| Теги | tags=["users"] |
| Описание параметров | Path(..., description="...") |
| Модель ответа | response_model=UserResponse |
| Статусы | responses={200: {"description": "OK"}} |
Заключение
Сегодня мы:
- 📖 Узнали о Swagger UI и ReDoc
- 📝 Добавляли описания и аннотации
- 🔍 Настраивали документацию
- 💡 Практические примеры








