Как разобрать список моделей с Pydantic
Я использую Pydantic для моделирования запросов и ответов на API.
Я определил User
учебный класс:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
Мой API возвращает список пользователей, с которыми я получаю requests
и преобразовать в диктовку:
users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]
Как я могу преобразовать этот дикт в список User
случаи?
Мое решение сейчас
user_list = []
for user in users:
user_list.append(User(**user))
9 ответов
Теперь это возможно с помощью parse_obj_as
.
from pydantic import parse_obj_as
users = [
{"name": "user1", "age": 15},
{"name": "user2", "age": 28}
]
m = parse_obj_as(List[User], users)
Чтобы подтвердить и расширить предыдущий ответ, вот "официальный" ответ на pydantic-github - Все кредиты на "dmontagu":
"Правильный" способ сделать это в pydantic - использовать "Custom Root Types". Вам по-прежнему нужно использовать модель контейнера:
class UserList(BaseModel):
__root__: List[User]
but then the following will work:
UserList.parse_obj([
{'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']},
{'id': '456', 'signup_ts': '2017-06-02 12:22', 'friends': ['you']},
])
(и поместит значения в корневое свойство).
К сожалению, я думаю, что для этого пока нет хорошей поддержки сериализации, поэтому я думаю, что когда вы собираетесь вернуть результаты, если вы хотите вернуть только список, вам все равно нужно будет вернуть UserList.корень.
Я не думаю, что в настоящее время существует унифицированный интерфейс, который дает вам сериализованную / неструктурированную версию модели, которая уважает root_model, но если это то, что вы ищете, возможно, стоит создать.
Вы можете попробовать это
from typing import List
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
class Users(BaseModel):
users: List[User]
users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]
m = Users(users=users)
print(m.dict())
Вы можете использовать понимание списка вместе с распаковкой dict в User
конструктор
user_list = [
User(**user) for user in users
]
Вы можете использовать __root__
Ключевое слово Pydantic:
from typing import List
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
class UserList(BaseModel):
__root__: List[User] # ⯇-- __root__
Чтобы создать ответ JSON:
user1 = {"name": "user1", "age": 15}
user2 = {"name": "user2", "age": 28}
user_list = UserList(__root__=[])
user_list.__root__.append(User(**user1))
user_list.__root__.append(User(**user2))
Ваша веб-платформа API может jsonify user_list
для возврата в виде массива JSON (в теле ответа).
Пидантик V2
Для адаптерного подхода см. ответы Дэвида-Асафа .
Другое решение — использовать RootModel :
from pydantic import BaseModel, RootModel
class User(BaseModel):
name: str
age: int
class PersonList(RootModel):
root: list[User]
users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]
это сработало для меня, используя понимание списка:
user_list = [User(**user) for user in users]
Я просто сидел в своем
models.py
список диктовок вроде этого:
from django.db import models
from pydantic import BaseModel
class CustomList(BaseModel):
data: list[dict]
У меня есть еще одна идея упростить этот код, если версия pydantic ниже 1.2, которая не поддерживает метод parse_obj_as .
user_list = []
for user in users:
user_list.append(User(**user))
простой способ
user_list = [User(**user) for user in users]