FastApi从SQLAlchemy返回关联数据失败,关联列表为空
问题描述
开发测试应用时,一个Test Config对应多个Test Case,数据已正确保存,但调用接口获取数据时test_cases字段返回空列表。
当前返回结果:
{ "spec_name": "string", "test_cases": [] }
期望返回格式:
{ "spec_name":"string", "test_cases":[ { "id":1, "TaskName":"test1" }, { "id":2, "TaskName":"test2" } ] }
相关代码如下:
路由代码
@router.get("/cases_conf/", response_model=list[ConfigItem]) def read_cases_by_config(cases: List, db: orm.Session = Depends(services.get_db)): cases = services.get_test_by_config(db=db) return cases
SQLAlchemy模型
class ConfigTable(Base): __tablename__ = 'ConfigTable' id = sql.Column(sql.Integer, primary_key=True) spec_name = sql.Column(sql.String(30), nullable=True) test_cases = relationship("TestCase", back_populates="owner") date_created = sql.Column(sql.DateTime, default=dt.datetime.utcnow) date_last_updated = sql.Column(sql.DateTime, default=dt.datetime.utcnow) class TestCase(Base): __tablename__ = 'TestCase' id = sql.Column(sql.Integer, primary_key=True) TaskName = sql.Column(sql.String(100), nullable=True) config_id = sql.Column(Integer, ForeignKey("ConfigTable.id"), nullable=True) owner = relationship("ConfigTable", back_populates="test_cases") date_created = sql.Column(sql.DateTime, default=dt.datetime.utcnow) date_last_updated = sql.Column(sql.DateTime, default=dt.datetime.utcnow)
Pydantic Schema
class TestCase(pydantic.BaseModel): TaskName: Optional[str] = None class Config: orm_mode = True class CaseItem(TestCase): config_id: Optional[int] = None class Config: orm_mode = True class CaseConfig(pydantic.BaseModel): spec_name: str class ConfigItem(CaseConfig): test_cases: list[TestCase] = [] class Config: orm_mode = True
数据查询逻辑
services.get_test_by_config执行代码:
return db.query(models.ConfigTable).all()
解决方案
1. 解决SQLAlchemy懒加载问题
SQLAlchemy中relationship默认是懒加载(lazy='select'),即只有当访问关联属性时才会触发查询,但当数据库会话关闭后(比如接口返回数据时会话已结束),无法再执行查询,导致test_cases为空。
有两种解决方式:
方式一:查询时主动预加载关联数据
修改services.get_test_by_config的查询逻辑,使用joinedload预加载test_cases:
from sqlalchemy.orm import joinedload def get_test_by_config(db: orm.Session): return db.query(models.ConfigTable).options(joinedload(models.ConfigTable.test_cases)).all()
方式二:修改relationship为立即加载
直接在ConfigTable的test_cases字段中设置lazy参数为'joined'或'selectin',确保查询Config时自动加载关联的TestCase:
test_cases = relationship("TestCase", back_populates="owner", lazy='joined')
2. 修正Pydantic模型字段
当前TestCase Pydantic模型未包含id字段,即使关联数据加载成功,也不会返回id值。需要添加id字段:
class TestCase(pydantic.BaseModel): id: Optional[int] = None # 添加该字段 TaskName: Optional[str] = None class Config: orm_mode = True
3. 清理路由冗余参数
路由函数中的cases: List参数是多余的,且未导入List会导致报错,应移除:
@router.get("/cases_conf/", response_model=list[ConfigItem]) def read_cases_by_config(db: orm.Session = Depends(services.get_db)): cases = services.get_test_by_config(db=db) return cases
内容的提问来源于stack exchange,提问作者rafaelHTML
相关产品推荐
相关产品推荐

