如何在SQLAlchemy关联查询的结果列表中访问列值
问题:SQLAlchemy左关联查询后无法访问列值
背景代码
模型定义
class Order(Base): __tablename__ = "orders" internal_id = Column(Integer, primary_key=True) total_cost = Column(Float, nullable=False) created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=text("now()")) customer_id = Column(Integer, ForeignKey("customers.id", ondelete="CASCADE"), nullable=False) customer = relationship("Customer") class Item(Base): __tablename__ = "items" id = Column(Integer, primary_key=True, nullable=False) internal_id = Column(Integer, nullable=False) price = Column(Float, nullable=False) description = Column(String, nullable=False) order_id = Column(Integer, ForeignKey("orders.internal_id", ondelete="CASCADE"), nullable=False) order = relationship("Order")
查询代码及报错
执行左关联查询后,尝试访问列值时触发AttributeError:
@router.get("/{order_id}") def get_orders(order_id: int, db: Session = Depends(get_db)): """ 获取指定ID的订单 """ # 预期SQL: select * from orders left join items on orders.internal_id = items.order_id where orders.internal_id = {order_id}; result = db.query(Order, Item).join(Item, Item.order_id == Order.internal_id, isouter=True).filter(Item.order_id == order_id).all() for i in result: print(i.description) # 此处报错
报错信息:
AttributeError: Could not locate column in row for column 'description'
解决方案
1. 明确查询结果的结构
db.query(Order, Item)返回的是元组列表,每个元组包含两个元素:(Order实例, Item实例),而非单个融合对象。直接通过i.description访问会报错,因为元组本身没有description属性。
2. 修正查询逻辑的错误
原代码中filter(Item.order_id == order_id)会过滤掉没有关联Item的Order(左关联失去意义),应该改为过滤Order.internal_id == order_id,这样才能匹配到目标订单及其所有关联Item(无Item时Item实例为None)。
3. 正确访问列值的方式
方式一:解构元组遍历
遍历结果时直接解构元组,分别获取Order和Item实例:
@router.get("/{order_id}") def get_orders(order_id: int, db: Session = Depends(get_db)): """ 获取指定ID的订单及关联商品 """ result = db.query(Order, Item).join(Item, Item.order_id == Order.internal_id, isouter=True).filter(Order.internal_id == order_id).all() for order, item in result: # 左关联可能返回无Item的情况,需判断item是否为None if item: print(item.description) # 访问Item的列 print(order.total_cost) # 访问Order的列
方式二:通过索引访问元组元素
如果不解构,也可以通过索引直接取元组中的对应实例:
for i in result: order = i[0] item = i[1] if item: print(item.description)
4. 更简洁的替代方案:利用SQLAlchemy关联关系
既然模型中已经定义了关联,可补充双向关联让逻辑更完整,之后直接查询Order实例,通过关联属性获取Item列表,无需手动写join:
# 补充双向关联定义(推荐) class Order(Base): # ... 其他字段 items = relationship("Item", back_populates="order") class Item(Base): # ... 其他字段 order = relationship("Order", back_populates="items") # 查询代码简化为: @router.get("/{order_id}") def get_orders(order_id: int, db: Session = Depends(get_db)): order = db.query(Order).filter(Order.internal_id == order_id).first() if order: # 直接通过关联属性获取所有Item for item in order.items: print(item.description)
内容的提问来源于stack exchange,提问作者experimental
相关产品推荐
相关产品推荐

