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

Pydantic root_validator异常行为:传入已有实例触发错误

问题原因与解决方案

核心原因

SQLModel中,当你给嵌套字段(比如B.others: List[A])传入已实例化的模型对象时,pre=True的root_validator仍然会被触发,但此时传入validator的values参数不再是创建实例时的原始字典,而是已经实例化的A对象。而你的root_validator逻辑是针对字典(比如调用items())设计的,自然会抛出AttributeError。

之所以会触发A的validator,是因为SQLModel的验证链会递归处理嵌套模型——哪怕你传入的是现成实例,它也会走一遍验证流程,而pre=True的validator是在所有字段解析前执行的,这时候还没进入“复用已有实例”的逻辑,就把实例当成了验证输入传进去了。

解决方法

在Base类的root_validator里加一个判断:如果传入的values是当前类的实例,直接返回即可,不需要执行字典相关的验证逻辑。

示例代码修改如下:

from sqlmodel import SQLModel, root_validator
from typing import List

class Base(SQLModel):
    @root_validator(pre=True)
    def base_validator(cls, values):
        # 先判断是不是当前类的实例,是就直接返回,跳过字典处理逻辑
        if isinstance(values, cls):
            return values
        # 下面是你原本的验证逻辑,比如检查必填字段、处理默认值等
        # 示例:确保某个字段存在(根据你的实际需求修改)
        # if "some_field" not in values:
        #     values["some_field"] = "default_value"
        return values

class A(Base):
    id: int
    name: str

class B(Base):
    id: int
    others: List[A] = []

# 测试正常运行
x = A(id=1, name="test")
z = B(id=2, others=[x])
print(z)

额外说明

如果你用的是SQLModel v2.x版本,官方推荐用@model_validator(mode="before")替代root_validator,逻辑是一样的:

from sqlmodel import SQLModel, model_validator

class Base(SQLModel):
    @model_validator(mode="before")
    def base_validator(cls, values):
        if isinstance(values, cls):
            return values
        # 原验证逻辑
        return values

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:30:05