Pydantic 字段验证装饰器field_validator教程
引言
在构建数据驱动的应用程序时,确保输入数据的准确性和完整性至关重要。Pydantic 是一个 Python 库,它提供了一种简单而强大的方式来验证和设置数据。在本教程中,我们将探讨如何使用 Pydantic 的 field_validator
装饰器来创建自定义的字段验证逻辑。
基础知识
在开始之前,请确保您已经安装了 Pydantic。如果没有,请使用以下命令安装:
pip install pydantic
创建 Pydantic 模型
首先,让我们创建一个简单的 Pydantic 模型。这个模型将包含一个名为 a
的字段。
from pydantic import BaseModel
class Model(BaseModel):
a: str
使用 field_validator
装饰器
field_validator
装饰器允许您为模型中的字段添加自定义验证逻辑。要使用它,请按照以下步骤操作:
- 导入
field_validator
: 从pydantic
导入field_validator
。
from pydantic import BaseModel, field_validator
- 定义验证函数: 创建一个类方法,该方法接受一个参数(要验证的值)并返回验证后的值。
class Model(BaseModel):
a: str
@field_validator('a')
@classmethod
def ensure_foobar(cls, v: Any):
if 'foobar' not in v:
raise ValueError('"foobar" not found in a')
return v
在这个例子中,我们定义了一个名为 ensure_foobar
的验证函数,它检查 a
字段的值是否包含子字符串 "foobar"
。
3. 应用装饰器: 使用 @field_validator('field_name')
语法将装饰器应用于验证函数。
4. 测试模型: 创建模型实例并测试验证逻辑。
# 正确的值
model = Model(a='this is foobar good')
print(model)
# 错误的值
try:
model = Model(a='snap')
except ValidationError as exc_info:
print(exc_info)
在上面的例子中,第一个模型实例成功创建,因为 a
字段的值包含 "foobar"
。第二个实例创建失败,因为值不包含 "foobar"
,因此抛出了 ValidationError
。
高级用法
field_validator
装饰器还支持一些高级功能,如:
- 验证多个字段: 通过传递多个字段名作为参数,可以创建一个验证函数来验证多个字段。
class Model(BaseModel):
a: str
b: str
@field_validator('a', 'b')
@classmethod
def validate_fields(cls, v: Any, values: Dict[str, Any]):
if 'foobar' not in v and 'foobar' not in values.get('b', ''):
raise ValueError('"foobar" not found in a or b')
return v
- 自定义验证模式: 通过设置
mode
参数,可以指定验证是在字段验证前还是验证后进行。
@field_validator('a', mode='before')
- 检查字段存在性: 通过设置
check_fields
参数,可以控制是否检查字段是否实际存在于模型中。
@field_validator('a', check_fields=False)
源码分析
以下是 field_validator
装饰器的基本结构和关键部分:
def field_validator(
field: str,
/,
*fields: str,
mode: FieldValidatorModes = 'after',
check_fields: bool | None = None,
) -> Callable[[Any], Any]:
# ...
参数解析
field
: 第一个字段名,作为位置参数传递。/
表示field
是一个位置参数,不能作为关键字参数传递。*fields
: 其他字段名,作为可变位置参数传递。mode
: 指定验证是在字段验证前还是验证后进行。check_fields
: 控制是否检查字段是否实际存在于模型中。
关键部分
- 参数检查:
- 检查
field
是否为函数类型。如果是,抛出错误,因为field_validator
应该用于字段和关键字参数,而不是单独使用。 - 检查所有字段名是否都是字符串类型。如果不是,抛出错误。
- 检查
- 内部装饰器定义:
- 定义一个内部函数
dec
,它接受一个可调用对象f
作为参数,并返回一个PydanticDescriptorProxy
对象。
- 定义一个内部函数
- 验证函数类型:
- 检查
f
是否是实例方法。如果是,抛出错误,因为field_validator
不能应用于实例方法。
- 检查
- 确保类方法:
- 确保
f
是一个类方法。
- 确保
- 创建装饰器信息:
- 创建一个包含字段信息、模式和字段检查标志的
FieldValidatorDecoratorInfo
对象。
- 创建一个包含字段信息、模式和字段检查标志的
- 返回代理对象:
- 返回一个
PydanticDescriptorProxy
对象,它包装了原始的函数f
和字段验证信息。
- 返回一个
这个装饰器的设计遵循了几个优秀的设计原则:
- 单一职责原则:
field_validator
只负责字段验证,不处理其他逻辑。 - 开闭原则:通过使用装饰器模式,可以轻松地扩展或修改字段验证逻辑,而不需要修改原始函数。
- 代码重用:通过装饰器,可以在多个模型中重用相同的验证逻辑。
此外,这段代码还展示了一些Python的高级特性,如类型注解、装饰器和元编程。
结论
在本教程中,我们学习了如何使用 Pydantic 的 field_validator
装饰器来为模型字段添加自定义验证逻辑。通过这个强大的工具,您可以确保输入数据符合您的特定要求,从而提高应用程序的健壮性和可靠性。