FastAPI查询PostgreSQL当前活跃用户所属商品的报错排查
问题根因
你遇到的报错和越权风险来自四处明确的代码错误:
- 触发AttributeError的直接原因:
list_products函数调用.all()返回的是匹配查询条件的Product实例列表,列表类型本身不存在owner_id属性,你写的products.owner_id属于对返回值类型的错误使用,代码运行到这一行就会直接崩溃,根本不会进入后续判断分支。 - 越权访问的逻辑漏洞:即使你修复了属性报错,分支内无参数调用
list_products(db=db)的逻辑没有传入任何过滤条件,会直接返回全表商品数据;且整个判断逻辑完全冗余——你已经先按当前用户id查了一次商品,再做权限判断属于完全多余的操作,也没有正确处理超级管理员的查询逻辑。 - 响应模型定义冲突:你贴出了两个同名的
ShowProduct模型,一个缺失size字段,一个包含该字段,重复定义会导致响应序列化时出现字段丢失、类型不匹配的问题。 - 路由路径写法不规范:
@app.get("users/me/items/")缺失路径开头的/,会导致FastAPI路由注册匹配不符合预期。
正确实现方案
1. 重构通用商品查询函数
给查询函数增加可选的owner_id过滤参数,兼顾普通用户的自有商品查询和超级管理员的全量查询需求:
def list_products(db: Session, owner_id: int | None = None): query = db.query(Product) # 传入owner_id时追加过滤条件,不传则查询全量 if owner_id is not None: query = query.filter(Product.owner_id == owner_id) return query.all()
2. 统一Pydantic响应模型
删除重复的ShowProduct定义,保留和数据库字段匹配的版本,避免序列化冲突:
class ShowProduct(BaseModel): name: str price: int size: str owner_id: int class Config: orm_mode = True
3. 修正路由业务逻辑
移除无效的列表属性判断,直接根据当前用户身份选择查询逻辑,同时补全路由路径的前缀斜杠:
@app.get("/users/me/items/", response_model=List[ShowProduct]) async def read_own_items( db: Session = Depends(get_db), current_user: Vendor = Depends(get_current_active_user) ): # 超级管理员查询全量商品,普通用户仅查询自己创建的商品 if current_user.is_superuser: products = list_products(db=db) else: products = list_products(db=db, owner_id=current_user.id) return products
效果验证
- 普通用户调用接口时,生成的SQL会自动携带
WHERE owner_id = 当前用户id过滤条件,无法访问其他用户创建的商品 - 超级管理员调用接口时不追加owner_id过滤条件,可返回全量商品数据
- 不会再出现
'list' object has no attribute 'owner_id'报错 - 接口响应会正常返回
name/price/size/owner_id四个字段,和你预期的返回结构一致
内容的提问来源于stack exchange,提问作者pythonGo
相关产品推荐
相关产品推荐

