You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pydantic模型字段间依赖的校验方案求解

解决Pydantic模型字段依赖校验的方案

方法1:根校验器(Root Validator)

用根校验器可以直接访问整个模型的字段值,集中处理版本与字段的依赖逻辑,完全符合单一父类的需求:

from pydantic import BaseModel, root_validator, ValidationError

# 从数据库获取的选项
options_v1 = ("a", "b", "c")
options_v2 = ("d", "e", "f")

class Model(BaseModel):
    version: int
    field: str

    @root_validator(skip_on_failure=True)
    def check_field_version_match(cls, values):
        version = values.get("version")
        field = values.get("field")
        
        if version == 1 and field not in options_v1:
            raise ValueError(f"version=1时,field必须是{options_v1}中的一个")
        elif version == 2 and field not in options_v2:
            raise ValueError(f"version=2时,field必须是{options_v2}中的一个")
        # 可按需扩展更多版本的校验规则
        return values

# 测试示例
try:
    valid_v1 = Model(version=1, field="a")
    print(valid_v1)
    valid_v2 = Model(version=2, field="d")
    print(valid_v2)
    invalid = Model(version=1, field="d")
except ValidationError as e:
    print(e)

skip_on_failure=True的作用是:如果version字段本身校验失败(比如传入非整数),会跳过这个校验器,避免无意义的报错。

方法2:字段校验器(Field Validator)

如果只需要针对field字段做校验,可以用字段校验器结合values参数获取版本值:

from pydantic import BaseModel, field_validator, ValidationError

options_v1 = ("a", "b", "c")
options_v2 = ("d", "e", "f")

class Model(BaseModel):
    version: int
    field: str

    @field_validator("field")
    def validate_field_by_version(cls, value, values):
        # Pydantic v2用values.data获取已校验字段,v1直接用values
        version = values.data.get("version")
        if version == 1 and value not in options_v1:
            raise ValueError(f"version=1时,field只能是{options_v1}中的值")
        elif version == 2 and value not in options_v2:
            raise ValueError(f"version=2时,field只能是{options_v2}中的值")
        return value

方法3:保留类型提示的动态校验

如果希望IDE能给出字段的类型提示(比如提示可选值),可以结合Literal和校验器实现:

from pydantic import BaseModel, ValidationError, root_validator
from typing import Literal, Union

options_v1 = ("a", "b", "c")
options_v2 = ("d", "e", "f")
FieldV1 = Literal[options_v1]
FieldV2 = Literal[options_v2]

class Model(BaseModel):
    version: int
    field: Union[FieldV1, FieldV2]

    @root_validator(skip_on_failure=True)
    def match_version_field(cls, values):
        version, field = values.get("version"), values.get("field")
        if version == 1 and field not in options_v1:
            raise ValueError(f"version=1时,field必须是{options_v1}中的一个")
        elif version == 2 and field not in options_v2:
            raise ValueError(f"version=2时,field必须是{options_v2}中的一个")
        return values

这种方式既保留了类型提示的优势,又实现了版本依赖的校验逻辑。

选型建议

优先用方法1,逻辑集中清晰,易于扩展,完全适配单一父类的需求;如果只关注field字段的校验,方法2更简洁;看重类型提示的话可以选方法3。

内容的提问来源于stack exchange,提问作者dino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:53:15