如何在Pydantic通用基类GeneralModel中为特定类型字段统一添加验证?
Pydantic全局特定类型字段统一验证方案
以下是几种基于GeneralModel实现全局特定类型字段验证的可行方案:
方案1:基模型中添加全局字段验证器
直接在GeneralModel中定义针对所有字段的验证器,通过类型判断只对目标类型执行校验逻辑。比如要统一验证所有字符串字段不为空:
from pydantic import BaseModel, field_validator from typing import Any class GeneralModel(BaseModel): class Config: use_enum_values = True exclude_none = True @field_validator("*", mode="before") def validate_non_empty_str(cls, value: Any, info) -> Any: # 仅对字符串类型字段执行验证 if isinstance(value, str): stripped_val = value.strip() if not stripped_val: raise ValueError(f"字段 [{info.field_name}] 不能为空字符串") return stripped_val # 非目标类型直接返回原值 return value
- 说明:
"*"匹配所有字段,mode="before"表示在字段类型转换前执行验证;若需在类型转换后验证(比如验证int是否为正),可改为mode="after"。
方案2:用Annotated定义带验证的通用类型
将验证逻辑与类型绑定,定义全局通用类型,子模型直接复用即可,灵活性更高:
from pydantic import BaseModel, StringConstraints, PositiveInt from typing import Annotated # 定义全局通用验证类型 NonEmptyStr = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)] PositiveNum = Annotated[int, PositiveInt] class GeneralModel(BaseModel): class Config: use_enum_values = True exclude_none = True # 子模型中直接使用预定义的验证类型 class User(GeneralModel): username: NonEmptyStr age: PositiveNum
- 说明:这种方式可以针对不同业务场景定义多种通用类型,验证规则清晰,便于维护。
方案3:全局替换类型的验证逻辑(Pydantic v2+)
通过model_validator在基模型中统一处理目标类型的验证,无需修改子模型字段定义:
from pydantic import BaseModel, model_validator, StringConstraints from typing import Annotated, Any # 定义目标类型的验证规则 validated_str_adapter = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)] class GeneralModel(BaseModel): class Config: use_enum_values = True exclude_none = True @model_validator(mode="before") def validate_all_str_fields(cls, values: dict[str, Any]) -> dict[str, Any]: for field_name, field in cls.model_fields.items(): # 判断字段类型是否为str if field.annotation is str: raw_value = values.get(field_name) # 应用预定义的验证规则 validated_value = cls.model_validate({field_name: raw_value}, from_attributes=False)[field_name] values[field_name] = validated_value return values
- 说明:该方案会对所有继承自
GeneralModel的子模型中的str字段自动应用验证逻辑,完全全局生效。
内容的提问来源于stack exchange,提问作者localhost
相关产品推荐
相关产品推荐

