Короткий ответ
Параметр response_model декоратора эндпоинта задаёт отдельную Pydantic-модель для исходящих данных; FastAPI сериализует возвращаемый объект именно по полям этой модели, отбрасывая лишние.
Как это работает подробнее
После выполнения функции-обработчика FastAPI прогоняет результат через указанную выходную модель (response_model=UserOut), даже если функция вернула объект с большим количеством полей (например, ORM-модель с паролем). В ответ попадут только поля, описанные в UserOut.
Пример кода
example.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserOut(BaseModel):
id: int
email: str
@app.get("/users/{user_id}", response_model=UserOut)
def get_user(user_id: int):
# предположим, объект из БД содержит ещё password_hash
return {"id": user_id, "email": "a@example.com", "password_hash": "secret"}
# Ответ клиенту: {"id": 1, "email": "a@example.com"} - password_hash отфильтрованЧто использовать на практике
- Практика. Разделение входной (
UserIn, с паролем) и выходной (UserOut, без пароля) модели — стандартная практика для защиты чувствительных данных и явного контроля контракта API.
Подводные камни
- Риск. Используют одну и ту же модель для входа и выхода и забывают, что в ней есть, например, поле
password_hash, которое утечёт в ответ; не задаютresponse_model, рассчитывая, что сериализация «сама всё уберёт».