from pydantic import BaseModel, Field, validator
# -----基本model定义-----
# 1.
class User(BaseModel):
"""
simple data model: User
"""
name : str # no default value means must give value
age: int # ... must give value
# 2. 基于pydantic的collection
from pydantic_collections import BaseCollectionModel
class UserCollection(BaseCollectionModel[User]):
"""
定义了User列表 的 data model,这样可以直接使用.dict()
"""
pass
# 3.
class UserContainer(BaseModel):
"""
BaseCollectionModel作为其他model的成员字段
"""
all_users : UserCollection = Field(None)
# --------以下测试---------
def pydantic_basic_usage():
single_user = User(name="hh", age=12)
# model to dict
d_data = single_user.dict()
# dict to model
single_user = User.parse_obj(d_data)
# take User into a list
l_user = [single_user]
f = f"user list format: {l_user}"
print(f) # user list format: [TestModel(name='hh', age=12)]。注意,这里不能l_user.dict(),因为l_user是list,没有dict方法
def pydantic_collections_usage():
user_data = [
{'name': 'Bender', 'age': 10},
{'name': 'Balaganov', 'age': 12},
]
# init an UserCollection
users = UserCollection(user_data)
# append an user to UserCollection
single_user = User(name="hh", age=12)
users.append(single_user) # ok
# users.append(user_data[0]) # failed. instance of User expected (type=type_error.arbitrary_type; expected_arbitrary_type=User)
print(users.dict(), users.json())
def pydantic_container_usage():
data = {
"all_users": [
{'name': 'Bender', 'age': 10},
{'name': 'Balaganov', 'age': 12},
]
}
container = UserContainer(**data)
print(container.dict())
def pydantic_validator_usage():
class UserWithValidator(BaseModel):
name : str = Field(None)
age : int = Field(None)
@validator("age")
def num_check(cls, v):
"""
v 表示 age 对应的值
"""
print("enter validator num_check")
if v < 0:
v = 0
if v > 100:
v = 100
# validate and modify
return v
@validator("name")
def lenth_check(cls, v):
"""
v 表示 name 对应的值
"""
print("enter validator lenth_check")
if len(v) > 6:
v = v[:6]
# validate and modify
return v
@validator("age", "name", pre=True)
def not_none(cls, v):
"""
必须全部赋值,不可为None
该 validator 在目标作用字段的其他所有validator之前执行
"""
print("enter validator not_none")
if v is None:
raise ValueError("None value exists")
return v
@validator("age")
def change_age_for_user_hhhhhh(cls, v, values):
"""
values:包含任何先前验证字段的名称到值映射的字典
修改用户hhhhhh的年龄为15岁
"""
print("enter validator change_age_for_user_hhhhhh")
user_name = values["name"]
if user_name == "hhhhhh":
v = 15
return v
single_user = UserWithValidator(name="hhhhhhhhh", age=-10)
print(single_user.dict())
# output:
# enter validator not_none
# enter validator lenth_check -> 到此都是check field 'name'
# enter validator not_none
# enter validator num_check
# enter validator change_age_for_user_hhhhhh -> 到此都是check field 'age'
# {'name': 'hhhhhh', 'age': 15}
# 可以看到,validator的执行顺序是:
# 1. 字段顺序优先,validator定义顺序优先
# 2. 我们可以给validator传递pre=True,让它在目标作用字段的其他所有validator之前执行
if __name__ == "__main__":
pydantic_basic_usage()
pydantic_collections_usage()
pydantic_container_usage()
pydantic_validator_usage()
网友评论