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

为何Pydantic模型验证器内__int/__str赋值不触发验证?

问题分析:Pydantic模型未触发预期验证的原因

问题代码

from pydantic import BaseModel, conint, constr, ValidationError, validator, Any, Optional

class IntOrStr(BaseModel):
    __int: Optional[conint(strict=True, le=100, ge=10)] = None
    __str: Optional[constr(strict=True, max_length=64, min_length=10)] = None
    value: Any

    @validator("value")
    def value_must_be_int_or_str(cls, v):
        try:
            __int = v # no validation. not sure why?
            return v
        except ValidationError as e:
            print(str(e))

        try:
            __str = v # no validation. not sure why?
            return v
        except ValidationError as e:
            print(str(e))

        raise ValueError("error. value must be int or str")

    class Config:
        validate_assignment = True

问题描述

执行p = IntOrStr(value=True)时,预期因True是布尔值无法通过__int和__str的验证,但实际__int = v和__str = v并未触发任何验证,原因如下:


核心原因

  • 直接赋值不触发Pydantic字段验证:你在validator里写的__int = v只是普通Python变量赋值,和模型定义的__int字段没有任何关联。Pydantic的字段校验逻辑只会在模型实例化、字段赋值(开启validate_assignment时)等框架触发的场景下运行,普通变量赋值不会调用这些校验规则。
  • 字段与变量名混淆:模型里的__int是私有字段,但你在validator里定义了同名局部变量,两者完全是不同的对象,局部变量的赋值操作根本不会触发表单字段的校验逻辑。

正确实现方式

要验证value是否符合__int或__str的规则,需要手动调用Pydantic的校验逻辑,比如用预定义的类型去校验值:

from pydantic import BaseModel, conint, constr, ValidationError, validator, Any

class IntOrStr(BaseModel):
    # 把类型定义抽成类属性,避免和实例字段混淆
    _int_validator = conint(strict=True, le=100, ge=10)
    _str_validator = constr(strict=True, max_length=64, min_length=10)
    value: Any

    @validator("value")
    def value_must_be_int_or_str(cls, v):
        # 用定义的校验器验证值
        try:
            cls._int_validator(v)
            return v
        except ValidationError:
            pass

        try:
            cls._str_validator(v)
            return v
        except ValidationError:
            pass

        raise ValueError("error. value must be int or str")

    class Config:
        validate_assignment = True

# 测试:此时传入True会触发验证失败
try:
    p = IntOrStr(value=True)
except ValueError as e:
    print(e)  # 输出:error. value must be int or str

补充说明

  • strict=True的作用是禁止自动类型转换(比如布尔值不能被当作整数),但必须通过Pydantic的校验入口触发才能生效。
  • 原代码中的__int、__str私有字段属于冗余定义,因为你并没有实际使用它们来存储或校验值,抽成类属性的校验器更符合逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:25:50