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

如何在Pydantic中根据age字段条件设置school字段为可选?

解决Pydantic Student模型中school字段的条件可选问题

需求回顾

需要实现一个Student模型:

  • 当age字段值小于6时,school字段可选
  • 当age字段值大于等于6时,school字段为必填项

原模型代码:

from pydantic import BaseModel

class Student(BaseModel):
    name: str
    age: int
    school: str

# 正常情况验证通过
student = Student(**{ "name": "Tom", "age": 10, "school": "Blabla"})
# 期望通过但实际报错
baby_student = Student(**{ "name": "Tom", "age": 5})

你之前尝试的问题分析

  1. 尝试代码1的问题:
    直接给values["school"] = None,但原模型中school被定义为str类型,不允许None值,因此触发ValidationError。

  2. 尝试代码2的问题:
    在root_validator中动态修改类的__annotations__是无效的——Pydantic在类定义阶段就已经完成了字段规则的解析,运行时修改不会生效,而且这种全局修改会破坏其他场景下的校验逻辑。

正确解决方案

方法1:Pydantic v2 写法(推荐)

先将school定义为Optional[str]并设置默认值None,再通过model_validator添加条件校验:

from pydantic import BaseModel, model_validator, ValidationError
from typing import Optional

class Student(BaseModel):
    name: str
    age: int
    school: Optional[str] = None

    @model_validator(mode='after')
    def check_school_required(self):
        # 当年龄>=6时,school必须不为空
        if self.age >= 6 and self.school is None:
            raise ValueError("school is required when age is 6 or older")
        return self

# 测试用例
student = Student(**{"name": "Tom", "age": 10, "school": "Blabla"})  # 验证通过
baby_student = Student(**{"name": "Tom", "age": 5})  # 验证通过

# 校验失败场景
try:
    invalid_student = Student(**{"name": "Alice", "age": 7})
except ValidationError as e:
    print(e)

方法2:Pydantic v1 写法

如果仍在使用Pydantic v1,可使用root_validator实现相同逻辑:

from pydantic import BaseModel, root_validator, ValidationError
from typing import Optional

class Student(BaseModel):
    name: str
    age: int
    school: Optional[str] = None

    @root_validator(skip_on_failure=True)
    def check_school_required(cls, values):
        age = values.get("age")
        school = values.get("school")
        if age >= 6 and school is None:
            raise ValueError("school is required when age is 6 or older")
        return values

# 测试用例同上

核心思路

先放宽school的字段类型允许None,再通过验证器补充条件必填的规则,既满足低龄学生无需填写school的需求,又保证高龄学生的school字段必须存在。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:58:26