FastAPI:如何配置SQLModel将嵌套对象扁平化为同一张数据库表?
解决方案:将嵌套对象扁平存储到同一张表
完全可以实现你的需求,通过在SQLModel模型中手动映射嵌套对象的字段到数据库表的列,同时保留API层面的嵌套结构。下面是具体实现方式:
方法1:手动属性映射(通用兼容所有数据库)
这种方法不依赖数据库特殊特性,通过定义数据库存储的扁平字段,再通过属性方法生成API需要的嵌套结构,兼容性最强。
步骤1:定义API用的嵌套模型
先创建用于API交互的InnerObject模型,无需映射到数据库表:
from pydantic import BaseModel class InnerObject(BaseModel): first_attribute: str second_attribute: str
步骤2:定义数据库模型并处理嵌套属性
创建OuterObject模型,包含数据库存储的扁平字段,同时通过属性方法实现嵌套的attributes字段:
from sqlmodel import SQLModel, Field, Column from pydantic import computed_field, root_validator class OuterObject(SQLModel, table=True): id: str = Field(sa_column=Column(nullable=False, primary_key=True)) name: str # 数据库表中实际存储的扁平字段 first_attribute: str second_attribute: str # 用于API响应的嵌套属性,不直接映射到数据库 @computed_field @property def attributes(self) -> InnerObject: return InnerObject( first_attribute=self.first_attribute, second_attribute=self.second_attribute ) # 处理API请求中传入的嵌套attributes,将值映射到扁平字段 @root_validator(pre=True) def unpack_attributes(cls, values): if "attributes" in values: attrs = values.pop("attributes") values["first_attribute"] = attrs.first_attribute values["second_attribute"] = attrs.second_attribute return values
效果说明
- 数据库层面:
OuterObject对应的表只会有id、name、first_attribute、second_attribute四个列,无需创建额外表存储InnerObject。 - API层面:请求时可传入嵌套的
attributes结构,响应时也会返回包含attributes的嵌套对象,完全匹配你的需求。
方法2:使用SQLAlchemy复合类型(仅支持部分数据库)
如果你的数据库支持复合类型(如PostgreSQL),可以直接使用SQLAlchemy的CompositeType简化代码:
from sqlalchemy import Column, String from sqlalchemy.types import CompositeType from sqlmodel import SQLModel, Field # 定义复合类型 class InnerObjectType(CompositeType): def __init__(self): super().__init__( "inner_object", [ Column("first_attribute", String), Column("second_attribute", String) ] ) class OuterObject(SQLModel, table=True): id: str = Field(sa_column=Column(nullable=False, primary_key=True)) name: str # 直接使用复合类型映射嵌套对象 attributes: InnerObject = Field(sa_column=Column(InnerObjectType()))
这种方式代码更简洁,但仅适用于支持复合类型的数据库,通用性不如第一种方法。
内容的提问来源于stack exchange,提问作者Otrebor
相关产品推荐
相关产品推荐

