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

如何在Pydantic子模型验证中使用父模型的属性?

在Pydantic子模型验证中访问父模型属性的方案

问题场景

给定以下JSON数据:

{
    "multiplier": 5,
    "field_1": {
        "value": 1
    },
    "field_2": {
        "value": 2
    }
}

对应的Pydantic模型定义如下:

from pydantic import BaseModel, validator

class Item(BaseModel):
    value: int

class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item

需求是:在验证Item的value字段时,需要使用父模型Container的multiplier属性进行逻辑校验或计算,同时避免在父层编写复杂的嵌套验证逻辑,也不在子模型中重复定义multiplier字段。

解决方案

直接在Item的普通字段验证器中无法直接获取父模型的属性,因为子模型验证上下文默认不包含父模型信息。以下是几种可行的实现方式:

方法1:通过验证上下文传递参数(Pydantic v1)

在父模型的根验证器中,将multiplier作为上下文传递给子模型,子模型的验证器通过kwargs获取上下文参数:

from pydantic import BaseModel, validator, root_validator

class Item(BaseModel):
    value: int

    @validator("value")
    @classmethod
    def validate_value(cls, value, **kwargs):
        # 从上下文获取父模型的multiplier,默认值为1
        multiplier = kwargs.get('context', {}).get('multiplier', 1)
        # 示例验证逻辑:value * multiplier不能超过30
        if value * multiplier > 30:
            raise ValueError(f"value * multiplier 不能超过30")
        # 返回计算后的值
        return value * multiplier

class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item

    @root_validator(pre=True)
    @classmethod
    def pass_multiplier_to_items(cls, values):
        multiplier = values.get('multiplier')
        if multiplier is not None:
            # 为每个Item字段传递包含multiplier的上下文
            for field_name in ['field_1', 'field_2']:
                if field_name in values:
                    values[field_name] = Item(**values[field_name], context={'multiplier': multiplier})
        return values

# 测试示例
data = {
    "multiplier": 5,
    "field_1": {"value": 1},
    "field_2": {"value": 2}
}
container = Container(**data)
print(container.field_1.value)  # 输出5
print(container.field_2.value)  # 输出10

方法2:利用Pydantic v2的模型验证器传递上下文

如果使用Pydantic v2,可以通过model_validator和ValidationInfo来传递上下文参数:

from pydantic import BaseModel, field_validator, model_validator
from pydantic_core import ValidationInfo

class Item(BaseModel):
    value: int

    @field_validator('value')
    @classmethod
    def validate_value(cls, v, info: ValidationInfo):
        # 从上下文获取multiplier
        multiplier = info.context.get('multiplier', 1)
        if v * multiplier > 30:
            raise ValueError(f"value * multiplier 不能超过30")
        return v * multiplier

class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item

    @model_validator(mode='before')
    @classmethod
    def inject_multiplier_context(cls, data):
        multiplier = data.get('multiplier')
        if multiplier:
            # 为每个Item字段注入上下文
            for key in ['field_1', 'field_2']:
                if key in data:
                    data[key] = Item.model_validate(data[key], context={'multiplier': multiplier})
        return data

# 测试示例
data = {
    "multiplier": 5,
    "field_1": {"value": 1},
    "field_2": {"value": 2}
}
container = Container(**data)
print(container.field_1.value)  # 输出5
print(container.field_2.value)  # 输出10

方法3:自定义通用嵌套模型(适配深层嵌套场景)

如果嵌套层级较深,可以定义通用的子模型类,统一处理父模型参数的传递:

from pydantic import BaseModel, validator, root_validator
from typing import TypeVar, Generic

T = TypeVar('T')

class BaseNestedItem(BaseModel, Generic[T]):
    value: int

    @validator("value")
    @classmethod
    def validate_value(cls, value, **kwargs):
        multiplier = kwargs.get('context', {}).get('multiplier', 1)
        if value * multiplier > 30:
            raise ValueError(f"value * multiplier 不能超过30")
        return value * multiplier

class Container(BaseModel):
    multiplier: int
    field_1: BaseNestedItem
    field_2: BaseNestedItem

    @root_validator(pre=True)
    @classmethod
    def pass_multiplier_context(cls, values):
        multiplier = values.get('multiplier')
        if multiplier:
            for field in ['field_1', 'field_2']:
                if field in values:
                    values[field] = BaseNestedItem(**values[field], context={'multiplier': multiplier})
        return values

说明

以上方法核心逻辑是通过验证上下文将父模型的属性传递给子模型,既避免了在父层编写复杂的嵌套字段遍历逻辑,也不需要在子模型中重复定义父模型的字段,适配深层嵌套的业务场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:42:24