查询单个字段时触发ValueError问题排查
解决SQLAlchemy查询单个字段后FastAPI返回ValueError的问题
问题现象
使用SQLAlchemy查询完整ORM对象时,FastAPI接口能正常返回结果;但查询单个字段(如Test.name)时,日志显示查询结果为元组列表(例如[('test_name_1',), ('test_name_2',)]),但接口返回时触发以下错误:
ValueError: [ValueError('dictionary update sequence element #0 has length 32; 2 is required'), TypeError('vars() argument must have dict attribute')]
原因分析
- 查询完整ORM对象时,返回的是带有
__dict__属性的模型实例,FastAPI默认序列化逻辑可正常处理。 - 直接查询单个字段(
session.query(Test.name).all())返回的是元组列表,FastAPI尝试将其当作字典结构处理时,会因元组不符合键值对格式要求,调用vars()或字典更新操作失败,从而抛出错误。
解决方案
方案1:转换为字典列表(最直接)
在Repository层将元组结果转换为带明确键的字典,让FastAPI可正常序列化:
from app.infrastructure.db import db from app.infrastructure.logging.logger import logger from app.models.test import Test # 确保导入Test模型 class TestRepository: def get_tests(self): with db.session() as session: logger.debug(f'Session: {session}') tests = session.query(Test.name).all() logger.debug(tests) # 将元组列表转换为字典列表 return [{"name": name} for (name,) in tests]
方案2:使用namedtuple包装结果
通过namedtuple创建带属性的轻量对象,模拟ORM实例结构:
from collections import namedtuple from app.infrastructure.db import db from app.infrastructure.logging.logger import logger from app.models.test import Test # 定义与查询字段匹配的namedtuple TestName = namedtuple("TestName", ["name"]) class TestRepository: def get_tests(self): with db.session() as session: tests = session.query(Test.name.label("name")).all() # 将查询结果转换为namedtuple实例 return [TestName(*row) for row in tests]
方案3:使用SQLAlchemy的keyed_tuple(进阶)
利用SQLAlchemy的keyed_tuple直接返回带键的结果:
from sqlalchemy.util import keyed_tuple from app.infrastructure.db import db from app.infrastructure.logging.logger import logger from app.models.test import Test class TestRepository: def get_tests(self): with db.session() as session: # 使用keyed_tuple让结果保留字段名 tests = session.query(keyed_tuple(Test.name, labels=["name"])).all() return tests
内容的提问来源于stack exchange,提问作者dansh
相关产品推荐
相关产品推荐

