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

Ответить

Вы можете использовать модель ormar в fastapi response_model вместо pydantic.

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

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

Это можно сделать несколькими способами в 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 в запросе, он будет проверен правильно (так как поле является необязательным), сохранен в базе данных и возвратит сохраненные записи без этого поля (также будет проверено).

!!!Note Обратите внимание, что, хотя вы не передаете значение поля, само поле по-прежнему существует в response_model, что означает, что оно будет отображаться в данных ответа и будет установлено значение None.

1
Если вы хотите перечитать поле из результатов.

FastApi Ответ_модель_Исключения

Fastapi имеет response_model_exclude, который принимает набор (или список) имен полей.

У этого есть свои ограничения, так как ormar и pydantic также принимают словари, в которых можно установить столбцы исключения/включения или на вложенных моделях (подробнее см. ниже).

Предупреждение: обязательное поле нельзя исключить при использовании response_model, так как в процессе проверки может произойти сбой.

1
2
3
app.post ("/users/", response_model =User, response_model_exclude ={"password"})
async def create_user (user: User):
    Return user.save ()

Верхняя точка может быть запрошена следующим образом:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Testclient Import TestClient

Client = TestClient(приложение)

С клиентом:
        # note There is no pk
        user = {
            "email": "test@domain.com",
            "password": "^*^%A*DA*IAAA",
            "first_name": "John",
            "last_name": "Doe",
        }
        response = client.post ("/users/", json=user)
        Note That the excluded field is fully gone from response
        «Passert password» не в ответе ()
        # read the response and initialize model out of it
        created_user = User(** response.json ())
        # note pk is populated by autoincrement
        assert created_user.pk is not None
        # note password is missing in initialized model too
        assert created_user.password is None

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

1
Заметьте, что вы можете использовать этот метод только для незапрошенных fields.

Вложенные модели, исключение

Хотя fastapi позволяет передавать только один набор имен полей, поэтому просто исключается, ormar гораздо умнее при использовании response_model_exclude.

В ormar для исключения вложенных моделей можно использовать два типа обозначений.

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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
«Органа»((
    metadata=metadata
    database= база данных
)

Категория (Ormar.Model):
    ormar_config = base_ormar_config.copy (tablename="categories")

    id: int = ormar.Integer(primary_key =True)
    name: str = ormar.String(max_length =255)    
    Priority: int = ormar.Integer(nullable=True)


Класс пользователя (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)
    Категория: Optional[Категория] = ormar.ForeignKey(Категория, related_name ="категория")

Если вы хотите исключить приоритет из категории ответа, вы все равно можете использовать параметр fastapi.

1
2
3
app.post ("/users/", response_model =User, response_model_exclude ={"category__priority"})
async def create_user (user: User):
    Return user.save ()

Обратите внимание, что вы можете использовать двойное подчеркивание для перехода к более глубоким моделям, и если вы хотите исключить несколько полей из вложенной модели, вам нужно добавить полный путь перед ними. В примере response_model_exclude={"category__priority", "category__other_field", category__nested_model__nested_model_field} ETC.

!!!Обратите внимание, что для получения дополнительной информации о возможных исключениях и о том, как создать словарь исключений или настройки, посетите раздел Поля документа

Обратите внимание, что в дополнение к параметру response_model_exclude, fastapi также поддерживает другие параметры, унаследованные от pydantic. Все они также подходят для ormar, но могут иметь некоторые нюансы, поэтому лучше читать раздел dict документа.

Исключено из модели.model_dump ()

Или вы можете просто вернуть словарь из ormar.Model и использовать его.

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

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

1
2
3
4
5
app.post ("/users2/", response_model =User)
async def create_user2(user: User)
    user = user.save ()
    return user. model_dump (exclude={'password'})
    # could be также something like return user. model_dump (exclude={'category'): {'priority'}to exclude category priority

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

Если вы хотите полностью исключить это поле таким образом, просто не используйте response_model и исключите его из модели_dump ().

Кроме того, вы можете вернуть только словарь из модели ormar. Таким образом, вы также можете настроить исключение/включение в словарь и исключить поля из вложенных моделей.

!!!Обратите внимание, что теоретически вы теряете проверку ответа здесь, но из-за того, что вы работаете на ormar.Models, данные ответа проверяются после запроса базы данных (так как ормар является pydantic моделью).

Таким образом, если полностью пропустить response_model, вы можете выполнить следующие действия:

1
2
3
4
app.post ("/users4/") # note no response_model
async def create_user4(user: User)
    user = user.save ()
    return user. model_dump (exclude={'last_name'})

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

1
The cost of this solution is that you loose also api documentation as response schema in unknown from fastapi perspective.

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

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

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

1
2
3
4
5
# generate a tree of models without password on User and without priority on nested Category
ResponseUser = User.get_pydantic (exclude={"password": ..., "category":{"priority"}})
app.post ("/users3/", responseUser) # use the generated model here
async def create_user3(user: User)
    Return user.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).

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

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

Образцы:

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

Pydantic Base-модель (Pydantic BaseModel)
    model_config = pydantic.configDict(from_attributes =True)

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


app.post ("/users3/", response_model =UserBase) # use pydantic model here
async def create_user3(user: User): #use ormar model here (but of course you use pydantic тоже here)
    Return user.save ()