FastAPI для начинающих: API с базой данных и тестамиВходные данные и Pydantic v2Модели создания и ответа

Модели создания и ответа

Уроки курсаМодели создания и ответа

Серверный id: кто его задаёт и почему он не во входной схеме

Поле id объявлено только в RoomOut, потому что его значение назначает обработчик, а не клиент. В обработчике это выглядит так:

def create_room(room: RoomIn):
    record = {"id": 1, "name": room.name, "capacity": room.capacity}
    return record

Значение 1 здесь — демонстрационное. В реальном приложении id приходил бы из базы данных после сохранения; здесь хранения нет, и id фиксирован только чтобы показать механику.

response_model не придумывает id и не подставляет никакого значения по умолчанию. Он получает уже собранный словарь и проверяет его. Если id там есть — хорошо, он попадёт в ответ. Если id отсутствует — FastAPI не придумает его, а вернёт серверную ошибку.

Частая ловушка — объявить id в RoomIn. Тогда Pydantic будет требовать id от клиента и проверять его по схеме. Если обработчик затем напишет {"id": room.id, ...}, он доверяет клиентскому значению — клиент фактически сам назначил себе идентификатор. Само по себе объявление поля в RoomIn не заставляет обработчик его использовать, но соблазн скопировать room.id в результат есть. Чтобы этот сценарий исключить, серверный id не появляется во входной схеме вовсе.

Отдельно: если клиент пришлёт JSON с ключом id, а поля id в RoomIn нет, Pydantic по умолчанию просто проигнорирует этот ключ — ошибки 422 не будет. Но в room.id обратиться не получится, потому что такого атрибута у модели нет.