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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:50:07