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

Pydantic v2中GetterDict的替代方案迁移技术问询

Pydantic v2 替代 GetterDict 实现单对象属性拆分到嵌套模型的方案

在Pydantic v2中,GetterDict已被移除,要实现将单个ORM对象的属性拆分到多个嵌套模型中的需求,可以通过**模型前置验证器(model_validator)**结合from_attributes配置来完成,以下是几种实用方案:

方案一:基础前置验证器拆分

直接在目标模型中添加前置验证器,手动将原对象分配给嵌套字段,利用嵌套模型的from_attributes能力自动提取所需属性:

from pydantic import BaseModel, model_validator
from typing import Any


class Source:
    a = 'a'
    b = 'b'
    c = 1


class RefTargetModel(BaseModel):
    b: str
    c: int
    # 开启从属性/ORM对象解析
    model_config = {'from_attributes': True}


class TargetModel(BaseModel):
    a: str
    ref: RefTargetModel

    model_config = {'from_attributes': True}

    @model_validator(mode='before')
    def split_attributes(cls, data: Any) -> Any:
        # 针对Source类型的输入做拆分处理
        if isinstance(data, Source):
            return {
                'a': data.a,
                'ref': data  # 将原对象传给嵌套模型,由它自动提取b、c
            }
        return data


# 替代v1的from_orm方法
target = TargetModel.model_validate(Source(), from_attributes=True)
print(target)
# 输出: a='a' ref=RefTargetModel(b='b', c=1)

方案二:通用嵌套映射(多嵌套字段场景)

如果需要拆分多个嵌套字段,可以定义嵌套字段与对应模型的映射关系,实现通用处理逻辑:

from pydantic import BaseModel, model_validator
from typing import Any, Dict, Type


class Source:
    a = 'a'
    b = 'b'
    c = 1
    d = 'd'
    e = 2


class RefTargetModel(BaseModel):
    b: str
    c: int
    model_config = {'from_attributes': True}


class AnotherRefModel(BaseModel):
    d: str
    e: int
    model_config = {'from_attributes': True}


class TargetModel(BaseModel):
    a: str
    ref: RefTargetModel
    another_ref: AnotherRefModel

    model_config = {'from_attributes': True}

    # 定义嵌套字段与对应模型的映射
    _nested_mappings: Dict[str, Type[BaseModel]] = {
        'ref': RefTargetModel,
        'another_ref': AnotherRefModel
    }

    @model_validator(mode='before')
    def split_nested_attributes(cls, data: Any) -> Any:
        if not isinstance(data, Source):
            return data
        
        processed_data = {'a': data.a}
        # 批量处理所有嵌套字段
        for field_name, model_cls in cls._nested_mappings.items():
            processed_data[field_name] = data
        return processed_data


target = TargetModel.model_validate(Source(), from_attributes=True)
print(target)
# 输出: a='a' ref=RefTargetModel(b='b', c=1) another_ref=AnotherRefModel(d='d', e=2)

方案三:计算字段+私有属性(复杂场景)

如果需要基于原对象做更多自定义计算,可以用私有属性存储原对象,再通过计算字段生成嵌套模型:

from pydantic import BaseModel, computed_field, PrivateAttr, model_validator
from typing import Any


class Source:
    a = 'a'
    b = 'b'
    c = 1


class RefTargetModel(BaseModel):
    b: str
    c: int
    model_config = {'from_attributes': True}


class TargetModel(BaseModel):
    a: str
    model_config = {'from_attributes': True}

    # 私有属性存储原ORM对象
    _original_obj: Any = PrivateAttr()

    @computed_field(return_type=RefTargetModel)
    def ref(self) -> RefTargetModel:
        # 从原对象生成嵌套模型
        return RefTargetModel.model_validate(self._original_obj, from_attributes=True)

    @model_validator(mode='before')
    def store_original_obj(cls, data: Any) -> Any:
        if isinstance(data, Source):
            return {
                'a': data.a,
                '_original_obj': data
            }
        return data


target = TargetModel.model_validate(Source(), from_attributes=True)
print(target)
# 输出: a='a' ref=RefTargetModel(b='b', c=1)

核心思路说明

Pydantic v2的设计更偏向显式的数据预处理,替代GetterDict的核心逻辑是:

  1. 利用model_validator(mode='before')在模型解析前拦截输入数据
  2. 将原ORM对象直接传递给对应的嵌套字段(或存储到私有属性)
  3. 嵌套模型通过开启from_attributes,自动从传入的对象中提取所需属性

这种方式比v1的GetterDict更直观,也更符合v2的类型安全设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:57:08