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

FastAPI+SQLAlchemy查询报错及过滤失效问题求助

问题解决方案

1. 字典属性访问错误(已修复,同时规范请求方式)

错误原因

初始代码用body.project_ids访问字典键,但Python字典仅支持[]语法取值,因此触发AttributeError: 'dict' object has no attribute 'project_ids'。你后续改为body['project_ids']的做法是正确的,但还有一个关键问题:

GET请求不应携带请求体,HTTP规范中GET请求的请求体属于未定义行为,部分客户端、网关或代理会忽略该请求体。建议改为以下两种合规方式之一:

  • 改用POST请求传递JSON数据(适合复杂参数)
  • 使用查询参数传递列表(适合简单参数)

2. SQLAlchemy过滤逻辑不生效

错误原因

SQLAlchemy列对象不能直接用Python原生in关键字构建IN查询。custom_datasets.c.project_id in body['project_ids']会被Python解释为「判断列对象是否在列表中」,结果恒为False,生成的SQL条件为WHERE false,自然无法匹配数据。正确做法是使用SQLAlchemy提供的in_()方法构建IN查询条件。

修复后的完整代码

main.py

import os
from sqlalchemy.orm import Session
from sqlalchemy import select, create_engine
from sqlalchemy.orm import sessionmaker
from typing import Dict, List
from fastapi import Depends, FastAPI, Body, Query

# 导入sql.py中的表定义
from sql import custom_datasets

app = FastAPI()

# 补全数据库会话初始化代码
engine = create_engine(os.getenv("REGISTRY_CONNECTION_STRING"))
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
    # 修复会话生成逻辑:确保连接正常关闭,且仅返回一个值
    if os.getenv("REGISTRY_CONNECTION_STRING"):
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()
    else:
        yield None

# 方案1:改用POST请求传递JSON体(推荐)
@app.post("/datasets/")
def get_project_registry(body: Dict[str, List[str]] = Body(...), db: Session = Depends(get_db)):
    if not db:
        return []
    
    # 使用SQLAlchemy的in_()方法构建IN查询
    stmt = select(custom_datasets).where(
        custom_datasets.c.project_id.in_(body['project_ids'])
    )
    res = db.execute(stmt).all()
    # 转换为字典列表便于返回
    return [dict(row._mapping) for row in res]

# 方案2:使用GET查询参数传递project_ids
@app.get("/datasets/")
def get_project_registry(project_ids: List[str] = Query(...), db: Session = Depends(get_db)):
    if not db:
        return []
    
    stmt = select(custom_datasets).where(
        custom_datasets.c.project_id.in_(project_ids)
    )
    res = db.execute(stmt).all()
    return [dict(row._mapping) for row in res]

测试请求示例

方案1(POST请求)

POST http://127.0.0.1:8009/datasets
Content-Type: application/json

{
    "project_ids": ["proj_id1"]
}

方案2(GET请求,查询参数)

GET http://127.0.0.1:8009/datasets?project_ids=proj_id1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:10:55