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

FastAPI查询PostgreSQL当前活跃用户所属商品的报错排查

问题根因

你遇到的报错和越权风险来自四处明确的代码错误:

  1. 触发AttributeError的直接原因:list_products函数调用.all()返回的是匹配查询条件的Product实例列表,列表类型本身不存在owner_id属性,你写的products.owner_id属于对返回值类型的错误使用,代码运行到这一行就会直接崩溃,根本不会进入后续判断分支。
  2. 越权访问的逻辑漏洞:即使你修复了属性报错,分支内无参数调用list_products(db=db)的逻辑没有传入任何过滤条件,会直接返回全表商品数据;且整个判断逻辑完全冗余——你已经先按当前用户id查了一次商品,再做权限判断属于完全多余的操作,也没有正确处理超级管理员的查询逻辑。
  3. 响应模型定义冲突:你贴出了两个同名的ShowProduct模型,一个缺失size字段,一个包含该字段,重复定义会导致响应序列化时出现字段丢失、类型不匹配的问题。
  4. 路由路径写法不规范:@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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:01:43