如何使用 Pydantic 解析模型列表

How to parse list of models with Pydantic

我使用 Pydantic 对 API 的请求和响应进行建模。

我定义了一个Userclass:

from pydantic import BaseModel

class User(BaseModel):
  name: str
  age: int

我的 API returns 我用 requests 检索并转换成字典的用户列表:

users = [{"name": "user1", "age": 15}, {"name": "user2", "age": 28}]

如何将此字典转换为 User 个实例的列表?

我现在的解决方案是

user_list = []
for user in users:
  user_list.append(User(**user))

你可以试试这个

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())

您可以考虑使用列表理解以及对 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 数组返回(在响应主体内)。

确认并扩展之前的 , here is an "official" answer at pydantic-github - 所有功劳归于“dmontagu”:

The "right" way to do this in pydantic is to make use of "Custom Root Types". You still need to make use of a container model:

class UserList(BaseModel):
    __root__: List[User]

但随后以下将起作用:

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']},
])

(and will put the values inside the root property).

Unfortunately, I think there is not good serialization support for this yet, so I think when you go to return the results, if you want to return just a list you'll still need to return UserList.root.

I don't think there is currently a unified interface that gets you a serialized/unstructured version of the model that respects the root_model, but if this is what you are looking for, it could be worth building.

现在可以使用 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 版本低于 1.2,不支持 parse_obj_as 方法,我有另一个简化此代码的想法。

user_list = []
for user in users:
  user_list.append(User(**user))

简单的方法

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]