Перейти к содержанию

Требования

Вы можете использовать модель ormar, а не pydantic в запросах для главного параметра fastapi.

При желании вы можете также комбинировать ormar.Models с pydantic.

Одной из наиболее распространенных задач в запросе является исключение определенных полей, которые вы не хотите включать в нагрузку, отправленную в API.

Это можно сделать несколькими способами в ormar, поэтому вы можете посмотреть на свои варианты ниже и выбрать тот, который лучше всего подходит для вашей ситуации.

Исключить поля из запроса

Необязательное поле

Обратите внимание на то, что каждое дополнительное поле не является обязательным, что означает, что дополнительные поля можно пропустить как в ответе, так и в запросе.

Поля не требуются, если (все/многие/все):

  • Поле помечается nullable=True
  • Поле имеет значение по умолчанию или функциональную функцию: default="Test"
  • Поле задано значение server_default
  • Field-это поле autoincrement=Trueprimary_key (Примечание: ormar.Integerprimary_key по умолчанию является autoincrement)

Примеры:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
«Органа»((
    metadata=metadata
    database= база данных
)

Класс пользователя (ormar.Model):
    ormar_config = base_ormar_config ()

    id: int = ormar.Integer(primary_key =True)
    Адрес электронной почты: str = ormar.String(max_length =255)
    password: str = ormar.String(max_length =255)
    first_name: str = ormar.String(max_length =255, nullable=True)
    last_name: str = ormar.String(max_length =255)
    категория: str = ormar.String(max_length =255, default="User")

В приведенном выше примере поля id (это целое число с автоматическим приращением), first_name (с nullable=True) и категория (со значением по умолчанию) являются необязательными, их можно пропустить в ответ, и модель все равно будет проверяться.

Если поле может быть пустым, его не нужно включать в полезную нагрузку во время создания и в ответ, поэтому, основываясь на приведенном выше примере, вы можете:

!!! Обратите внимание, что, хотя вам не нужно передавать дополнительные поля, вы все равно можете это сделать. Если кто-то передает значение, оно будет использоваться позже, если вы не предпримете шаги, чтобы предотвратить его.

1
2
3
4
# note that app is an FastApi
app.post ("/users/", response_model =User) # here we use ormar.Model in response
async def create_user (user: User): # here we use ormar.Model in request parameter
    Return user.save ()

Это означает, что, если вы не указали имя ie first_name в запросе, он будет правильно проверен (поскольку поле является необязательным), и None будет сохранен в базе данных.

Создание Pydantic модели из ormar.Model

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

Метод get_pydantic (), доступный для всех классов модели.

1
2
3
4
5
6
# generate a tree of models without password on User and without priority on nested Category
RequestUser = User.get_pydantic (exclude={"password": ..., "category":{"priority"}})
app.post ("/users3/", response_model =User) # here you can also use both ormar/pydantic
async def create_user3(user: RequestUser): # use the generated model here
    Комментарии: Now User is pydantic and not ormar Model so you need to convert
    return await User(** user.model_dump ()).save()

!!! Обратите внимание, чтобы увидеть больше примеров и узнать больше, посетите раздел get_pydantic документа.

Предупреждение Метод get_pydantic создает все модели в дереве вложенных моделей на основе алгоритма, который позволяет избежать циклов в модели (тот же алгоритм, что и в model_dump (), select_all () и т. д.)

1
2
3
То есть, что неофициально модельные модели не имеют ссылок на Parent Model (от default ormar relation is bidirectional).

Это означает, что вы можете привести в действие или включить в него различные стильки в древе больше, чем это было бы лучше, чем другие стильные модели (each occurrence will have separate own models).

Mypy и проверка типов

Обратите внимание, что назначение функции как типа Python будет проходить во время выполнения (так как не проверяется), и статические инспекторы типа, такие как mypy, будут жаловаться.

Хотя результат вызова функции всегда одинаков для данной модели, использование типов, созданных динамически, не допускается.

У вас есть два варианта:

Первый просто добавить # type:ignore, чтобы пропустить проверку типа

1
2
3
4
5
RequestUser = User.get_pydantic (exclude={"password": ..., "category":{"priority"}})
app.post ("/users3/", response_model =User)
async def create_user3(user: RequestUser): # type: ignore
    Комментарии: Now user is not ormar Model so you need to convert
    return await User(** user.model_dump ()).save()

Второй, немного более хаки, использует fastapi для извлечения аргументов функции.

Вы можете перезаписать запись__annotations__для данного параметра.

1
2
3
4
5
6
7
8
RequestUser = User.get_pydantic (exclude={"password": ..., "category":{"priority"}})
# Do not use the app decorator
async def create_user3(user: User): # use ormar model here
    return await User(** user.model_dump ()).save()
# overwrite the function annotations entry for user param with generated model
create_user3._annotations__["user"] = RequestUser
# manually call app functions (приложение.get, app.post и т. д.) and pass your function reference
app.post ("/categories/", response_model =User)(create_user3)

Обратите внимание, что это приведет к тому, что mypy «подумает», что пользователь является ормарской моделью, но это не имеет значения в запросе (в любом случае вы передаете jsonized District и должны быть преобразованы перед сохранением).

Это все равно должно работать правильно, так как полученная модель будет подмножеством полей, поэтому все необходимые поля будут проверены, а все неиспользуемые поля будут выведены из строя во время выполнения.

Автономная модель консольной

Конечным решением является создание отдельной pydantic модели вручную. Она работает точно так же, как и обычное приложение fastapi, поэтому вы можете использовать различные модели ответа, запроса и т. д.

Образцы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Import pydantic

Пользовательский Create (pydantic BaseModel):
    model_config = pydantic.configDict(from_attributes =True)

    Электронная почта: str
    fir_name: str
    last_name: str
    password: str


app.post ("/users3/", response_model =User) # use ormar model here (but of course you CAN use pydantic also here)
async def create_user3(user: UserCreate): # use pydantic model here
    Комментарии: Как сейчас request param is a pydantic model and not the ormar one
    # so you need to parse/convert it to ormar before you can use database
    return await User(** user.model_dump ()).save()