FastAPI PUT端点用Depends(get_db)报错:'UserBase'无'query'属性
解决FastAPI PUT端点
AttributeError: 'UserBase' object has no attribute 'query'问题 问题根源
报错的核心原因是函数名冲突导致递归调用,进而让db参数被错误赋值为UserBase对象:
- PUT端点的函数名为
update_user,而你在函数末尾调用的update_user(db, existing_user_record, update_user_request)实际上是在调用这个端点函数本身,而非你预期的数据库更新业务函数。 - 递归调用时参数传递完全错位:端点函数的参数顺序是
update_user_request: UserBase, username: str, db: Session,当你传入db作为第一个参数时,它会被赋值给update_user_request参数,原本的update_user_request会被赋值给db参数,导致后续db.query()调用时,db实际是UserBase对象,自然没有query属性。
你观察到PUT的db类型返回两个对象,正是递归调用时参数混乱导致的异常输出。
解决方案
- 重命名函数避免冲突:将端点函数和数据库业务逻辑函数的名称区分开,避免递归调用。
- 调整参数顺序:把路径参数
username放在请求体参数之前,符合FastAPI常规写法,减少混淆。 - 确保调用正确的业务函数:明确调用独立的数据库更新逻辑函数,而非端点函数本身。
修改后的代码示例
以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
相关产品推荐
相关产品推荐

