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

如何修改Pydantic嵌套模型使其返回指定字段而非对象

解决方案:在FastAPI的Pydantic模型中返回company_name而非整个company对象

针对你的需求,这里提供几种实用的实现方式:

方法1:直接修改模型结构并手动映射字段

直接将模型中的company: _CompanyBase替换为company_name: str,然后在实例化DTO时,从原始的company对象中提取name字段赋值给company_name。

修改后的模型

from typing import Optional
from datetime import date

class UserDTO(InternalEntity):
    keycloak_user_id: str
    first_name: str
    last_name: str
    gender: str
    email: str
    role: UserRole
    phone_number: str
    birthdate: Optional[date] = None
    address: Optional[_AddressBase] = None
    job: Optional[_JobBase] = None
    company_name: str
    isactive: bool

数据映射示例

如果从数据库或其他数据源获取到包含company对象的用户数据,可按如下方式转换为DTO:

# 假设原始用户数据(或ORM模型实例)
raw_user = {
    "keycloak_user_id": "kc_12345",
    "first_name": "张三",
    "last_name": "李四",
    "gender": "男",
    "email": "zhangsan@example.com",
    "role": UserRole.ADMIN,
    "phone_number": "13800138000",
    "birthdate": date(1990, 1, 1),
    "address": {"street": "XX街道", "city": "北京"},
    "job": {"title": "工程师"},
    "company": {"name": "科技有限公司", "id": "cmp_67890"},
    "isactive": True
}

# 转换为UserDTO
user_dto = UserDTO(
    # 展开除company外的所有字段
    **{k: v for k, v in raw_user.items() if k != "company"},
    company_name=raw_user["company"]["name"]
)

# 如果是SQLAlchemy ORM实例
# user = db.query(User).filter(User.id == 1).first()
# user_dto = UserDTO(
#     keycloak_user_id=user.keycloak_user_id,
#     first_name=user.first_name,
#     # ... 其他字段
#     company_name=user.company.name,
#     isactive=user.isactive
# )

方法2:使用Pydantic计算字段(v2版本)

利用Pydantic v2的computed_field特性,自动从company对象提取name,同时设置company字段序列化时排除,无需手动映射。

实现代码

from typing import Optional
from datetime import date
from pydantic import computed_field, Field

class UserDTO(InternalEntity):
    keycloak_user_id: str
    first_name: str
    last_name: str
    gender: str
    email: str
    role: UserRole
    phone_number: str
    birthdate: Optional[date] = None
    address: Optional[_AddressBase] = None
    job: Optional[_JobBase] = None
    # 设置exclude=True,序列化时自动排除该字段
    company: _CompanyBase = Field(exclude=True)
    isactive: bool

    # 计算字段,自动生成company_name
    @computed_field(return_type=str)
    def company_name(self) -> str:
        return self.company.name

使用方式

实例化DTO时直接传入包含company对象的数据,序列化时会自动返回company_name而不包含company:

user_dto = UserDTO(**raw_user)
# 转换为字典或JSON返回
return user_dto.model_dump()  # 结果中仅包含company_name

方法3:Pydantic v1版本兼容方案

如果你使用的是Pydantic v1,可以通过root_validator自动提取company_name:

实现代码

from typing import Optional
from datetime import date
from pydantic import root_validator

class UserDTO(InternalEntity):
    keycloak_user_id: str
    first_name: str
    last_name: str
    gender: str
    email: str
    role: UserRole
    phone_number: str
    birthdate: Optional[date] = None
    address: Optional[_AddressBase] = None
    job: Optional[_JobBase] = None
    company_name: str
    isactive: bool

    class Config:
        orm_mode = True  # 支持从ORM模型实例直接转换

    @root_validator(pre=True)
    def extract_company_name(cls, values):
        # 从传入的company对象中提取name
        if company := values.get("company"):
            values["company_name"] = company.get("name")
            # 删除原始company字段,避免模型验证报错
            del values["company"]
        return values

使用方式

直接传入包含company的数据即可自动转换:

user_dto = UserDTO(**raw_user)
return user_dto.dict()  # 返回包含company_name的字典

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:03:15