Существует ли передовая практика определения необязательных полей в моделях Pydantic?

Я работаю с Pydantic для проверки данных в проекте Python и столкнулся с проблемой при указании необязательных полей в моем файле BaseModel.

from pydantic import BaseModel

class MyModel(BaseModel):
    author_id: int | None    # Case 1: throws error
    author_id: Optional[int] # Case 2: throws error
    author_id: int = None    # Case 3: works

Теперь, запрашивая конечную точку, которая принимает указанную выше модель в качестве тела JSON, я не предоставляю поле author_id в запросе.

Когда я использую author_id: int | None, я получаю сообщение об ошибке, сообщающее, что обязательное поле отсутствует. Однако, если я изменю его на author_id: Optional[int], я столкнусь с той же ошибкой. Но когда я использую author_id: int = None или author_id: Optional[int] = None, модель работает как положено, без ошибок. (Работает, если присутствует =)

Есть ли у вас какие-либо рекомендации о том, как правильно определять необязательные поля в моделях Pydantic? Существует ли конкретная версия Pydantic (или другой библиотеки), поддерживающая int | Нет синтаксиса правильно?

  • питон == 3.11
  • пидантик == 2.8.1
  • фастапи==0.111.1

🤔 А знаете ли вы, что...
Python имеет множество фреймворков для веб-разработки, такие как Django и Flask.


1
51
2

Ответы:

Я думаю, что случай 1 является каноническим решением, но вы еще не определили необязательное поле (поскольку вы не указали значение по умолчанию). Вы хотите:

from pydantic import BaseModel


class MyModel(BaseModel):
    author_id: int | None = None

С этим определением:

>>> MyModel()
MyModel(author_id=None)
>>> MyModel(author_id=1)
MyModel(author_id=1)

Решено

Причина, по которой вы столкнулись с ошибкой, заключается в том, что не существует значения по умолчанию. Аннотации сами по себе ничего не делают.

Все приведенные ниже варианты работают и внутри практически эквивалентны. Третий вариант теперь рекомендуется для проектов, использующих только Python 3.10+.

from pydantic import BaseModel

class MyModel(BaseModel):
    author_id: Optional[int] = None # the original way
    author_id: Union[int, None] = None # another option
    author_id: int | None = None # more modern option (Python 3.10+)