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

FastAPI PUT端点用Depends(get_db)报错:'UserBase'无'query'属性

解决FastAPI PUT端点AttributeError: 'UserBase' object has no attribute 'query'问题

问题根源

报错的核心原因是函数名冲突导致递归调用,进而让db参数被错误赋值为UserBase对象:

  1. PUT端点的函数名为update_user,而你在函数末尾调用的update_user(db, existing_user_record, update_user_request)实际上是在调用这个端点函数本身,而非你预期的数据库更新业务函数。
  2. 递归调用时参数传递完全错位:端点函数的参数顺序是update_user_request: UserBase, username: str, db: Session,当你传入db作为第一个参数时,它会被赋值给update_user_request参数,原本的update_user_request会被赋值给db参数,导致后续db.query()调用时,db实际是UserBase对象,自然没有query属性。

你观察到PUT的db类型返回两个对象,正是递归调用时参数混乱导致的异常输出。

解决方案

  1. 重命名函数避免冲突:将端点函数和数据库业务逻辑函数的名称区分开,避免递归调用。
  2. 调整参数顺序:把路径参数username放在请求体参数之前,符合FastAPI常规写法,减少混淆。
  3. 确保调用正确的业务函数:明确调用独立的数据库更新逻辑函数,而非端点函数本身。

修改后的代码示例

以src/routers/users.py为例:

# src/routers/users.py
from src.database import get_db
from src.models import Users
from src.schemas import UserBase, UserCreate
from sqlalchemy.orm import Session
from fastapi import APIRouter, HTTPException, Depends

router = APIRouter()

# 定义独立的数据库更新业务函数(如果之前未定义,需要补充)
def db_update_user(db: Session, user_record: Users, update_data: UserBase):
    user_record.username = update_data.username
    user_record.password = update_data.password
    user_record.email = update_data.email
    user_record.created_at = update_data.created_at
    db.commit()
    db.refresh(user_record)
    return user_record

@router.post("/users", response_model=UserCreate, status_code=201)
async def create_users(create_user_request: UserCreate, db: Session = Depends(get_db)):
    print(type(db))
    record_check = (
        db.query(Users).filter(Users.username == create_user_request.username).first()
    )

    if record_check:
        raise HTTPException(
            status_code=403,
            detail="Username already exists!  Please select another username.",
        )

    return create_user(db, create_user_request)

# 重命名端点函数,避免和业务函数冲突
@router.put("/users/{username}", response_model=UserBase)
def update_user_endpoint(
    username: str,  # 路径参数前置,符合常规写法
    update_user_request: UserBase,
    db: Session = Depends(get_db)
):
    print(type(db))

    existing_user_record = db.query(Users).filter(Users.username == username).first()

    if not existing_user_record:
        raise HTTPException(
            status_code=400,
            detail="That old Username doesn't exist!  Please select another username.",
        )

    new_record_check = (
        db.query(Users).filter(Users.username == update_user_request.username).first()
    )

    if new_record_check:
        raise HTTPException(
            status_code=403,
            detail="The new requested Username already exists!  Please select another username.",
        )

    # 调用独立的业务函数,而非端点函数
    return db_update_user(db, existing_user_record, update_user_request)

额外注意

  • 确保create_user也是独立的数据库业务函数,和端点函数名称无冲突。
  • 路径参数前置是FastAPI的常规写法,虽然框架能自动识别参数类型,但这样的写法更清晰,能减少参数顺序导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 11:42:49