如何在Pydantic的__get_validators__中按顺序调用自定义校验函数
实现方案
你需要为emailId字段定义一个绑定了校验逻辑的自定义类型,在该类型的__get_validators__方法中按你需要的执行顺序yield校验函数即可,校验器的执行顺序和yield顺序完全一致,且前一个校验器的返回值会作为后一个校验器的入参。
具体实现步骤如下:
步骤1:修正原有模型的错误
你原有代码中私有属性_valid_emails的定义有误,先修正:
from pydantic import BaseModel from typing import List class PayloadValidator(BaseModel): """ 该模型用于校验负载结构和每个负载属性 """ tenantId: str # 后续会替换为自定义类型 emailId: List[str] role: str # 表示负载中的邮箱存在重复 _duplicates: bool = False # 表示负载中的邮箱已被当前请求的租户使用 _existing: bool = False # 表示负载中的邮箱是非企业邮箱 _non_corp_emails: bool = False # 最终邀请邮箱列表,修正类型标注和默认值 _valid_emails: List[str] = []
步骤2:定义自定义邮箱列表类型,绑定校验顺序
你需要自定义一个继承自List[str]的类型,在该类型的__get_validators__方法中按你期望的顺序yield校验器,这里我们会把你原有三个业务校验函数包装为符合Pydantic校验规范的方法:
from typing import Any, Dict, List # 导入你原有三个校验函数 from your_module import email_format, email_existance, duplicate_emails class ValidatedEmailList(List[str]): @classmethod def __get_validators__(cls): # 按你需要的执行顺序yield校验器,顺序可自行调整 yield validate_duplicate_emails yield validate_email_format yield validate_email_existance
步骤3:实现适配Pydantic规范的校验包装函数
Pydantic校验器默认接收当前字段值v、已校验完成的其他字段字典values两个参数,你可以从values中获取tenantId等字段传递给原有业务校验函数:
def validate_duplicate_emails(v: List[str], values: Dict[str, Any]) -> List[str]: # 调用原有重复校验函数,根据你函数的实际返回逻辑处理即可 has_duplicate, processed_emails = duplicate_emails(v) # 给模型私有属性赋值 values["_duplicates"] = has_duplicate # 返回处理后的邮箱列表给下一个校验器 return processed_emails def validate_email_format(v: List[str], values: Dict[str, Any]) -> List[str]: # 调用原有格式校验函数 is_valid, processed_emails = email_format(v) values["_non_corp_emails"] = not is_valid return processed_emails def validate_email_existance(v: List[str], values: Dict[str, Any]) -> List[str]: # 从已校验字段中取tenantId传给原有存在性校验函数,剩余参数按你的业务逻辑补充 tenant_id = values.get("tenantId") has_exist, valid_emails = email_existance(v, tenant_id, "你的其他参数") values["_existing"] = has_exist values["_valid_emails"] = valid_emails return v
步骤4:替换模型中emailId的字段类型
将原有PayloadValidator的emailId类型替换为我们定义的ValidatedEmailList即可:
class PayloadValidator(BaseModel): """ 该模型用于校验负载结构和每个负载属性 """ tenantId: str emailId: ValidatedEmailList role: str _duplicates: bool = False _existing: bool = False _non_corp_emails: bool = False _valid_emails: List[str] = []
补充说明
- 如果你原有校验函数遇到非法输入会直接抛出异常,Pydantic会自动捕获异常并转换为标准化的校验错误返回,无需额外处理
- 校验器的执行顺序完全和
__get_validators__中yield的顺序一致,你可以根据业务需求调整yield的先后顺序
内容的提问来源于stack exchange,提问作者Jeet Patel
相关产品推荐
相关产品推荐

