pydantic模块之多级定义和数据检查

464 阅读2分钟

1.多级schema定义

from enum import Enum
from typing import List, Union
from datetime import date
from pydantic import BaseModel
​
​
class Gender(str, Enum):
    man = "man"
    women = "women"
​
​
class Person(BaseModel):
    name: str
    gender: Gender
​
​
class Department(BaseModel):
    name: str
    lead: Person
    cast: List[Person]
​
​
class Group(BaseModel):
    owner: Person
    member_list: List[Person] = []
​
​
class Company(BaseModel):
    name: str
    owner: Union[Person, Group]
    regtime: date
    department_list: List[Department] = []

对于这种schema,我们可以逐步按照Gender、Person、Department、Group、Company的顺序依次进行实例化。也可以事先准备一个Company完整内容的字典,一次性直接实例化Company

tom_department = {
    "name": "Tom",
    "lead": {"name": "Jerry", "gender": "women"},
    "cast": [{"name": "Jerry", "gender": "women"}, {"name": "Jack", "gender": "man"}],
}
​
lucy__department = {
    "name": "Lucy",
    "lead": {"name": "lihua", "gender": "women"},
    "cast": [
        {"name": "lihua", "gender": "women"},
        {"name": "xiaoming", "gender": "man"},
    ],
}
company = {
    "name": "yyy",
    "owner": {"name": "victor", "gender": "women"},
    "regtime": "2021-12-24",
    "department_list": [tom_department, lucy__department],
}
company = Company(**company)
print(company.json())

result:

{"name": "yyy", "owner": {"name": "victor", "gender": "women"}, "regtime": "2021-12-24", "department_list": [{"name": "Tom", "lead": {"name": "Jerry", "gender": "women"}, "cast": [{"name": "Jerry", "gender": "women"}, {"name": "Jack", "gender": "man"}]}, {"name": "Lucy", "lead": {"name": "lihua", "gender": "women"}, "cast": [{"name": "lihua", "gender": "women"}, {"name": "xiaoming", "gender": "man"}]}]}

2.数据检查方法

基本数据类型的检查可以利用pydantic提供的检查方法来完成。复杂的数据类型的定义和检查需要通过validator和config来完成。

2.1 validator

比如下面的针对用户密码合理性的校验

from pydantic import BaseModel, validator
import re
​
class Password(BaseModel):
    password: str
​
    @validator("password")
    def password_rule(cls, password):
        def is_valid(password):
            if len(password) < 3 and len(password) > 10:
                return False
            if not re.search(r'[a-z]', password):
                return False
            if not re.search(r'[A-Z]', password):
                return False
            if not re.search(r'[\d]', password):
                return False
            return True
        if not is_valid(password):
            raise ValueError("密码不合理")

2.2 config

如果某一模型中的字段有统一的格式,可以使用config来进行输出检查。比如下面的密码,要求长度介于6位到20位之间

from pydantic import BaseModel
​
​
class Password(BaseModel):
    password: str
​
    class config:
        min_anystr_length = 6
        max_anystr_length = 20

这里有2点要注意 如果需要email验证,可以添加email_validator

python3.8之前要使用Literal, 需要安装typing-extensions

pip install pydantic[email]
pip install pydantic[typing-extensions]