about
本篇基于:pydantic2.4.1+python3.11.5
英文官档:https://docs.pydantic.dev/2.4/
严格模式和宽松模式的换算表:Conversion Table - Pydantic
版本差异
pydantic1.x和pydantic2.x是有版本差异的,pydantic2.x使用rust对pydantic的核心验证逻辑pydantic-core进行重写,据官网说比v1版本快乐5-50倍。
所以v2和v1在使用上也有差异,这点需要注意。
并且,v2版本搭配使用Python3.7及以上版本。
安装
pydantic模块安装
bash
# 标准安装
pip install pydantic==2.4.1
# 如果需要校验邮箱,可以额外安装 email-validator,pip install email-validator
# 如果支持.env设置,需要额外安装 python-dotenv, pip install python-dotenv
pip install email-validator==2.0.0.post2
pip install python-dotenv==1.0.0
pycharm安装pydantic插件
然后重启pycharm。
模型类校验
如果你学过Django的forms组件,你对接下来要学习的知识点不会陌生。
pydantic提供BaseModel类,对传入的数据进行校验,校验通过之后,我们可以拿到干净的数据,如果校验失败,则报错。
我们在项目开发中,可以使用BaseModel和对应的orm进行结合,对数据进行校验操作。
基本使用
python
# 使用前先导入
from pydantic import BaseModel
class User(BaseModel): # 自定义的模型类必须继承BaseModel
# 然后你可以在这里对字段进行约束
id: int # 没有默认值的字段,必须传值
name: str = 'zhangkai' # 有默认值的字段,可传可不传
# 按照规定的类型进行正常的传值
user1 = User(id=1)
print(user1.id, user1.name)
# 对于id字段的值是int,你传个字符串,pydantic内部会尝试转为int类型,能转就不报错,但ide会有错误提示
user1 = User(id="2", name='likai')
print(user1.id, user1.name)
# 转不了就报错了,Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='aa', input_type=str]
user1 = User(id="aa", name='likai')
print(user1.id, user1.name)
将需要校验的数据,传递给模型类,同时可以拿到一个模型类对象。而模型类在实例化对象的过程中,则会对传入的数据进行校验,校验通过返回对象;如果校验失败,则会抛出ValidationError
的错误。
访问模型类对象的属性
来看下通过模型类校验后,返回的对象,我们可以点出来哪些常用方法或者属性。
python
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = 'zhangkai'
# 按照规定的类型进行正常的传值
user = User(id=1, name='likai')
# print(user.id, user.name) # 1 likai
# 返回实例化对象时,我们传入了哪些字段给模型类
# print(user.model_fields_set) # {'name', 'id'}
# 返回模型类中定义的所有的字段信息
# print(user.model_fields)
"""
{
'id': FieldInfo(annotation=int, required=True),
'name': FieldInfo(annotation=str, required=False, default='zhangkai')
}
"""
# 返回模型字段和值,字典格式
# print(type(user.model_dump()), user.model_dump()) # <class 'dict'> {'id': 1, 'name': 'likai'}
# 返回模型字段和值,json字符串格式
# print(type(user.model_dump_json()), user.model_dump_json()) # <class 'str'> {"id":1,"name":"likai"}
# print(type(user.model_json_schema()), user.model_json_schema())
"""
<class 'dict'>
{
'properties': {
'id': {
'title': 'Id', 'type': 'integer'
},
'name': {
'default': 'zhangkai', 'title': 'Name', 'type': 'string'
}
},
'required': ['id'],
'title': 'User',
'type': 'object'
}
"""
# 返回模型类的浅拷贝对象,如果你需要深拷贝,请自行导入copy进行处理
# user.model_copy()
数据校验
数据校验的几个阶段
Annotated Validators
官档:https://docs.pydantic.dev/2.4/concepts/validators/#annotated-validators
python
from typing import List
from typing_extensions import Annotated
from pydantic import BaseModel, ValidationError
from pydantic import BeforeValidator, AfterValidator
def before(v: int) -> int:
assert v % 2 == 1, f'{v}的余数不等于1'
# 校验通过必须返回原值,或者处理后的值
return v
def after(v: int) -> int:
assert v % 2 == 0, f'{v}的余数不等于0'
# 校验通过必须返回原值,或者处理后的值
return v
MyNumber = Annotated[int, BeforeValidator(before), AfterValidator(after)]
class DemoModel(BaseModel):
num: MyNumber
num_list: List[MyNumber] # 如果是序列类型,那么内部校验时,会循环校验传递来的每个元素是否合法
try:
# 校验成功
obj = DemoModel.model_validate({"num": 1, "num_list": [1, 2, 3]})
print(obj.model_dump())
except ValidationError as exc:
print(exc)
"""
4 validation errors for DemoModel
num
Assertion failed, 1的余数不等于0 [type=assertion_error, input_value=1, input_type=int]
For further information visit https://errors.pydantic.dev/2.4/v/assertion_error
num_list.0
Assertion failed, 1的余数不等于0 [type=assertion_error, input_value=1, input_type=int]
For further information visit https://errors.pydantic.dev/2.4/v/assertion_error
num_list.1
Assertion failed, 2的余数不等于1 [type=assertion_error, input_value=2, input_type=int]
For further information visit https://errors.pydantic.dev/2.4/v/assertion_error
num_list.2
Assertion failed, 3的余数不等于0 [type=assertion_error, input_value=3, input_type=int]
For further information visit https://errors.pydantic.dev/2.4/v/assertion_error
"""
pre校验器
each_item
自定义验证器的错误信息
python
from pydantic import BaseModel, ValidationError
class User(BaseModel):
id: int
name: str
res = User.model_validate({'id': 1, 'name': "zhangkai"})
# 校验通过
print(res) # id=1 name='zhangkai'
try:
# 校验失败
User.model_validate({'id': "AAA", 'name': "zhangkai"}) # strict mode
except ValidationError as exc:
print(exc)
"""
1 validation error for User
id
Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='AAA', input_type=str]
For further information visit https://errors.pydantic.dev/2.4/v/int_parsing
"""
跳过验证
严格模式和宽松模式
python
from pydantic import BaseModel, ValidationError
class MyModel(BaseModel):
x: int
print(MyModel.model_validate({'x': '123'})) # lax mode
try:
MyModel.model_validate({'x': '123'}, strict=True) # strict mode
except ValidationError as exc:
print(exc)