Pydantic
Pydantic 数据验证
field_validator
本文档使用 MrDoc 发布
-
+
首页
Pydantic 数据验证
### Pydantic 数据验证方式 > [官方文档:Pydantic Validators](https://docs.pydantic.dev/latest/concepts/validators/) Field validators - field after validators - field before validators - field plain validators - field wrap validators Model validators - model before validators - model after validators - model wrap validators ### 1. 使用 Annotated 可以使用python自带的`Annotated` 来实现字段的验证 >w Python 中的 `Annotated` 主要用于`在不改变原有类型的情况下为类型添加额外的元数据` > 这些元数据可以是任何东西,比如说明文档,或者验证器,或者是额外的属性 > Python 本身并不会使用这些元数据,主要是提供给第三方工具 ``` from typing_extensions import Any, Annotated from pydantic import BeforeValidator, AfterValidator, BaseModel, ValidationError def integer(val: Any): try: return int(val) except Exception as e: print(e) raise ValueError(f"invalid data: val={val}") # 是否是偶数 def is_even(value: int) -> int: if value % 2 == 1: raise ValueError(f'{value} is not an even number') return value class Model(BaseModel): age: Annotated[int, BeforeValidator(integer)] number: Annotated[int, AfterValidator(is_even)] ``` #### 优势: - 使用`Annotated`定义验证器的优势在于,验证器可以重复使用,而且可以很明显的看出来这个字段有哪些验证器; - 如果使用`field_validator`,不仅不能复用,而且无法直观的看出来每个字段有哪些验证器; 重复使用验证器的示例: ``` class UserDetail(BaseModel): age: Annotated[int, BeforeValidator(integer)] class UserPublic(BaseModel): age: Annotated[int, BeforeValidator(integer)] ``` ### 2. 使用 field_validator 当然,field_validator 也不是一无是处,`它的优势在于可以同时为多个字段提供验证` ``` from pydantic import BaseModel, field_validator class Model(BaseModel): f1: str f2: str @field_validator('f1', 'f2', mode='before') @classmethod def capitalize(cls, value: str) -> str: return value.capitalize() ``` #### 优势 - 可以同时为多个字段提供验证,比如要验证多个时间参数的格式 ### 3. 使用 model_validator `model_validator` 是 Pydantic 提供的一个重要装饰器,用于验证整个模型的数据。它可以: - 访问模型的所有字段 - 在模型验证过程中的不同阶段进行验证 - 修改或转换数据 基本用法: ``` from pydantic import BaseModel, model_validator class UserModel(BaseModel): username: str password: str password_confirm: str @model_validator(mode="before") @classmethod def check_passwords_match(cls, data): # 必须是类方法,因为这时还没有生成对象 if isinstance(data, dict): if data.get('password') != data.get('password_confirm'): # 验证失败时应该抛出 ValueError 或其他异常 raise ValueError('密码不匹配') # 必须返回处理后的数据 return data @model_validator(mode="after") def check_username_not_password(self): # 必须是对象方法 if self.username == self.password: raise ValueError('用户名不能与密码相同') # 必须返回实例对象 return self ``` `model_validator` 有两种模式: 1. `mode="before"` - 在数据被转换为模型字段之前执行 - 接收原始输入数据 - 必须是类方法(使用 @classmethod) - 可以修改输入数据 2. `mode="after"` - 在所有字段验证完成后执行 - 接收已经实例化的模型 - 是实例方法 - 可以访问所有验证后的字段 注意事项: - `mode="before"` 验证器必须返回处理后的数据; - `mode="after"` 验证器必须返回模型实例; - 验证失败时应该抛出 `ValueError` 或其他异常; - 在一个模型中可以有多个验证器; - 验证器的执行顺序是:`before -> 生成对象(包含字段验证) -> after`; ### 4. `ValidationInfo` 参数 `field_validator`和`model_validator` 都可以给验证函数提供额外的参数`ValidationInfo`,该参数包含了以下属性: ``` class ValidationInfo(Protocol): """传递给验证函数的额外参数""" @property def context(self) -> Any | None: """用户定义的上下文""" pass @property def config(self) -> CoreConfig | None: """The CoreConfig that applies to this validation.""" pass @property def mode(self) -> Literal['python', 'json']: """The type of input data we are currently validating""" pass @property def data(self) -> Dict[str, Any]: """已经验证的数据""" pass @property def field_name(self) -> str | None: """当前字段名称(仅对field_validator有效)""" pass ```
gaojian
2025年1月23日 23:58
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码