SQLAlchemy - condition on join fails with AttributeError: Neither 'BinaryExpression' object nor 'Comparator' object has an attribute 'selectable'

SQLAlchemy - condition on join fails with AttributeError: Neither 'BinaryExpression' object nor 'Comparator' object has an attribute 'selectable'

我运行正在使用 Pyramid 使用 SQLAlchemy。我正在尝试 运行 具有自定义 'join' 条件的查询:

DBSession.query(A)\
        .outerjoin(A.b, B.a_id == A.id)\
        .all()

但是查询失败并出现以下错误:

AttributeError: Neither 'BinaryExpression' object nor 'Comparator' object has an attribute 'selectable'

问题源于条件,如果我删除它,查询有效:

DBSession.query(A)\
        .outerjoin(A.b)\
        .all()

我不明白这个问题,因为我遵循 the documentation 中描述的语法:

q = session.query(User).join(Address, User.id==Address.user_id)

有人看到发生了什么事吗?

好的,我看到了。 如果添加自定义条件,则语法不是 .outerjoin(A.b, ...),而是 .outerjoin(B, ...)

他们应该都接受,真的

(错误信息可能稍微更明确)

另一种说法是,如果您已经通过 .outerjoin(A.b... 指定了关系,则不再需要指定条件,实际上不能同时指定。

此错误的另一个可能原因是 join() 的显式 ON 子句使用不正确:显式 ON 子句应该是单个表达式。因此,如果您打算在 ON 子句中使用多个过滤器,则应将它们与 and_/or_ 结合使用。例如,如果您想在连接的 ON 子句中添加一个附加条件:

query(A).join(B, A.b_id = B.id, A.x > N)  # WRONG!
query(A).join(B, and_(A.b_id = B.id, A.x > N))  # CORRECT

Query.join() SQLA API doc 本身非常详细,但在摘要中有些含糊(它说它是 join(*args, **kwargs) 并没有多大帮助)。以下是 一些Query.join():

的正确可能用法的总结
# declare the join using own field which leads to the related object:
query(A).join(A.b)


# declare the join using a class of the related mapper:
query(A).join(B)


# same as above (using related mapper class) but use explicit ON clause
# ON clause can be any/"complex" expression
query(A).join(B, A.b_id = B.id)
query(A).join(B, _and(A.b_id = B.id, ...))


# reverse the order of the join (useful to do a right outer join for example):
query(A).select_entity_from(B).join(A, isouter=True)

在上面的所有示例中,除了第一个:

  • 带有显式 ON 子句的 AB 不仅可以是映射器 classes,还可以是任何 "selectable": subquery() 实例Table 或别名 (aliased(selectable)) 即可。
  • 没有明确的 ON 子句 AB 只能是映射器 class 或 Table 实例