如何修改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
相关产品推荐
相关产品推荐

