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

查询单个字段时触发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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:47:38