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

FastAPI中SQLModel返回JSON时丢失子列表数据问题排查

问题原因

Relationship是SQLAlchemy的ORM关联字段,SQLModel默认不会将这类字段纳入Pydantic的序列化范围——尽管SQLAlchemy会在Session内加载关联数据(所以你能打印出values),但FastAPI使用response_model=TableRecord时,会严格按照模型定义的数据字段来序列化,而Relationship字段不属于这个范畴,因此返回的JSON里会缺失该字段。

解决方案

方案1:创建专用响应模型(推荐)

定义独立的响应模型,显式包含需要序列化的关联字段,同时避免循环引用和ORM细节泄露:

from typing import List, Optional
from sqlmodel import SQLModel
from datetime import datetime

# 先定义子模型的响应结构
class TableRecordValueResponse(SQLModel):
    id: Optional[int]
    column_id: int
    value: str
    updated_on: Optional[datetime]
    updated_by: int

# 定义父模型的响应结构,包含关联的values字段
class TableRecordResponse(SQLModel):
    record_key: Optional[int]
    table_id: int
    created_by: int
    values: List[TableRecordValueResponse] = []

然后修改接口,使用新的响应模型,并主动加载关联数据(避免懒加载潜在问题):

from sqlalchemy.orm import selectinload

@table_records_router.get("/table_records/{record_key}", response_model=TableRecordResponse)
def get_table_record(record_key: int):
    with Session(engine) as session:
        # 使用selectinload主动加载关联的values数据
        statement = select(TableRecord).options(selectinload(TableRecord.values)).where(TableRecord.record_key == record_key)
        table_record = session.exec(statement).first()
        if not table_record:
            raise HTTPException(status_code=404, detail=f"TableRecord with key {record_key} not found")
        return table_record

方案2:修改原ORM模型,让Relationship字段可序列化

如果不想创建新模型,可以修改TableRecord的values字段定义,将其同时标记为Pydantic可序列化的字段:

class TableRecord(SQLModel, table=True):
    __tablename__: str = "table_record"
    record_key: Optional[int] = Field(default=None, primary_key=True)
    table_id: int
    created_by: int

    # 通过Field显式定义为Pydantic字段,并关联ORM关系
    values: list["TableRecordValue"] = Field(
        default=[],
        sa_column=Relationship(back_populates="table_record")
    )

注意:这种方式可能会引入循环引用问题,需要确保TableRecordValue的定义能被正确识别,同时查询时依然需要主动加载关联数据(用selectinload或joinedload)。

额外注意点
  • 务必主动加载关联数据:如果只使用基础查询,SQLAlchemy默认会用懒加载(lazy="select"),在Session关闭后访问values会报错,且序列化时可能无法正确获取数据。使用selectinload(适合一对多)或joinedload(适合内连接)可以提前加载关联数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:35:34