一、背景
在api接口中,需要验证一些参数;如django、flask 有些组件支持参数的校验;
但是适用场景具有针对性,定制化程度过高,扩展性不强;
如果想自定义一些参数,则可已选用这个模块pydantic
二、官方文档
pip install pydantic
三、案例
-
案例一
: 验证如下
验证不能为空
验证默认值
验证布尔类型
验证验证启用别名
验证时间模块
验证非必传Optional
验证数组类型 [1, 2, '3']
验证多个类型其中之一即可 Union[int, str]
自定义验证@validator
from enum import Enum, IntEnum
from datetime import datetime, date
from typing import List, Union
from typing import Optional
from pydantic import BaseModel, Field, ValidationError, validator
class UserModel(BaseModel):
user_id: int # 必传项, 可以为int 可以str类型int
username: str # 必传项, 可以为int 可以str类型int
gender: str # 必传值, 此处为自定义校验
active: bool = False # bool 类型 默认值 False
school = "吹灯大学" # 添加新字段修改值
address: str = Field(alias="addr") # 将传入addr输出为address
create_time: datetime
signup_ts: Optional[datetime] = None
merge: Union[int, str] # 数据可以允许多种数据类型 zhangsan, 123 均可
age: Optional[int] # 非必传参数, 默认值为None
tag: List[int] = [] # 传入数组类型
@validator("gender")
def check_gender(cls, v):
if v not in ["male", "female"]:
raise ValueError("sex is wrong!!!")
return v
data = {
"user_id": 12345,
"username": 1456789,
"age": 18,
"gender": "male",
"addr": "北京潘家园",
'aa': False,
'tag': [1, '2', 3],
"create_time": "2022-09-12 03:04:05",
"merge": "123a"
}
try:
user = UserModel(**data)
print(user.dict())
print(user.json())
except ValidationError as e:
print(e)
{'user_id': 12345, 'username': '1456789', 'gender': 'male', 'active': False, 'address': '北京潘家园', 'create_time': datetime.datetime(2022, 9, 12, 3, 4, 5), 'merge': '123a', 'age': 18, 'tag': [1, 2, 3], 'school': '吹灯大学'}
{"user_id": 12345, "username": "1456789", "gender": "male", "active": false, "address": "\u5317\u4eac\u6f58\u5bb6\u56ed", "create_time": "2022-09-12T03:04:05", "merge": "123a", "age": 18, "tag": [1, 2, 3], "school": "\u5439\u706f\u5927\u5b66"}
注: 如int传入的str类型的int则转成int
如int传入float 类型的int则保留整数
-
案例二
: 枚举类型校验
class GenderEnum(IntEnum):
male = 0
female = 1
class ShirtEnum(str, Enum):
S = "Small"
M = "Medium"
L = "Large"
class ConfigModel(BaseModel):
user_id: int
username: str
gender: GenderEnum
shirt: ShirtEnum = ShirtEnum.S # 设置默认
data = {
"user_id": 12345,
"username": 1456789,
"book": 2,
"shirt": "Small"
"test": "zhangsan"
}
user = ConfigModel(**data)
print(user.dict())
print(user.gender.value) # 输出值 0
print(user.shirt.value) # 输出值 Small
{'user_id': 12345, 'username': '1456789', 'gender': <GenderEnum.male: 0>, 'shirt': <ShirtEnum.S: 'Small'>}
- 案例三:
高级复杂检查
--> 数组-与对象的嵌套应用
class SchoolModel(BaseModel):
sch_id: int = 100
school: str
class UserModel(BaseModel):
user_id: int # 必传项, 可以为int 可以str类型int
username: str # 必传项, 可以为int 可以str类型int
age: int = 18 # 默认值 18
gender: GenderEnum
class UserListModel(BaseModel):
tag: List[int] = []
school: SchoolModel
users: List[UserModel]
data = {
"tag": [1, 3, '5', 7],
"school": {"sch_id": 12345, "school": "上海中学"},
"users": [
{"user_id": 12345, "username": "zhangsan", "gender": 1, "book": 2},
{"user_id": 12354, "username": "lisi", "gender": 1, "book": 2},
{"user_id": 12543, "username": "wanger", "gender":1, "book": 2},
]
}
user = UserListModel(**data)
print(user.dict())
print(user.school.sch_id) # 输出值 上海中学
print(user.users)
{'tag': [1, 3, 5, 7], 'school': {'sch_id': 12345, 'school': '上海中学'}, 'users': [{'user_id': 12345, 'username': 'zhangsan', 'age': 18, 'gender': <GenderEnum.female: 1>}, {'user_id': 12354, 'username': 'lisi', 'age': 18, 'gender': <GenderEnum.female: 1>}, {'user_id': 12543, 'username': 'wanger', 'age': 18, 'gender': <GenderEnum.female: 1>}]}
[UserModel(user_id=12345, username='zhangsan', age=18, gender=<GenderEnum.female: 1>), UserModel(user_id=12354, username='lisi', age=18, gender=<GenderEnum.female: 1>), UserModel(user_id=12543, username='wanger', age=18, gender=<GenderEnum.female: 1>)]
- 案例四:
高级复杂检查
--> Field应用
用于为模型架构或复杂验证提供有关字段的额外信息。一些参数仅适用于数字字段(int
、float
、Decimal
),有些仅适用于str
:param default factory:可调用,当此字段需要默认值时将调用它
如果同时设置了default和default factory,则会引发错误。
:param alias:字段的公共名称
:param title:可以是架构中使用的任何字符串
:param multiple of:仅适用于数字,要求字段为“的倍数”。这个架构将有一个“multipleOf”验证关键字
:param regex:仅适用于字符串,要求字段与正则表达式匹配模式字符串。架构将有一个“pattern”验证关键字
:param**extra:任何其他关键字参数都将按原样添加到架构中
如果default未定义且default\U factory未为None:
raise VALUERROR(不能同时指定default和default工厂)
default: Any = Undefined,
default_factory: Optional[NoArgAnyCallable] = None,
alias: str = None,
title: str = None,
description: str = None,
const: bool = None,
gt: float = None,
ge: float = None,
lt: float = None,
le: float = None,
multiple_of: float = None,
min_items: int = None,
max_items: int = None,
min_length: int = None,
max_length: int = None,
regex: str = None,
**extra: Any,
data2 = {"username": '12345', "weight": 77, "age": 33, "height": '2.16'}
class UserModel(BaseModel):
username: str = Field(default=None, description='姓名', min_length=3, max_length=16)
weight: int = Field(default=0, description='体重', gt=60, lt=90) # gt 大于 lt 小于
age: int = Field(default=18, description='年龄', ge=18, le=50) # ge 大于等于 le 小于等于
height: float = Field(default=1.75, description='身高', ge=1.67, le=2.22)
school: str = "996"
user = UserModel(**data2)
print(user.dict())
参考
- 官方文档 https://pydantic-docs.helpmanual.io/