Модели Pydantic
Данные для создания и изменения записей клиент присылает в теле запроса, в JSON. Чтобы проверить такой JSON, в FastAPI описывают модели на библиотеке Pydantic.
Модель
from pydantic import BaseModel, Field
class TodoIn(BaseModel):
title: str = Field(min_length=1, max_length=100)
priority: int = Field(3, ge=1, le=5) # 3 — значение по умолчанию
done: bool = False
Модель — класс с полями и типами, похожий на dataclass. Pydantic проверяет каждое поле: тип, ограничения Field(...), обязательность (поле без значения по умолчанию обязательно).
Тело запроса
@app.post("/todos", status_code=201)
def create(todo: TodoIn):
item = {"id": next_id(), **todo.model_dump()}
TODOS[item["id"]] = item
return item
- параметр-модель FastAPI читает из JSON в теле запроса;
- если JSON не подходит (нет
title,priority= 9, строка вместо числа), клиент получит 422 с описанием ошибок — ваша функция даже не вызовется; todo.title,todo.priority— поля уже нужного типа;todo.model_dump()— словарь;status_code=201в декораторе — код успешного ответа (201 Created для создания).
Модель ответа
class UserOut(BaseModel):
id: int
name: str
@app.get("/users/{uid}", response_model=UserOut)
def get_user(uid: int):
return USERS[uid] # в словаре есть и password_hash
response_model проверяет ответ и оставляет только поля модели. Так в ответ не попадут внутренние данные: хеш пароля, служебные поля. Её же FastAPI показывает в документации /docs как схему ответа.
Часто делают несколько моделей одной сущности: TodoIn — что присылает клиент, TodoOut — что он получает (с id), TodoPatch — для изменения.
Частичное обновление
class TodoPatch(BaseModel):
title: str | None = Field(None, min_length=1, max_length=100)
done: bool | None = None
@app.patch("/todos/{tid}")
def update(tid: int, patch: TodoPatch):
TODOS[tid].update(patch.model_dump(exclude_unset=True))
return TODOS[tid]
Метод PATCH меняет только присланные поля. model_dump() вернул бы все поля, и неприсланные стали бы None. exclude_unset=True оставляет только поля, которые клиент действительно прислал.
Итог
BaseModel, типы иField(min_length, max_length, ge, le);- параметр-модель — тело запроса, неверные данные — 422 автоматически;
status_code=201,response_modelпрячет лишние поля;- PATCH и
model_dump(exclude_unset=True).