【问题标题】:Can not apply filter on @hybrid_property in sqlalchemy无法在 sqlalchemy 中对 @hybrid_property 应用过滤器
【发布时间】:2014-04-30 07:49:11
【问题描述】:

代码很简单:

Class A(Base):
    status = Columns(Integer)

    @hybrid_property
    def is_ok(self):
        return self.status > 0

但是

session.query(A).filter(A.is_ok).all()

将引发异常:TypeError: Boolean value of this clause is not defined。

我试过print result[0].is_ok, type(result[0].is_ok)。是True <type 'bool'>。

那么我该如何根据hybrid_property进行过滤


我的答案

在@van 的帮助下,我有点知道该怎么做了。

参数filter(*criterion) 应该是SQL expression object。我曾经认为它需要一个布尔值作为 arg,BUT NO!

条件是任何适用于 select 的 WHERE 子句的 SQL 表达式对象。字符串表达式通过 text() 构造强制转换为 SQL 表达式构造。

代码告诉:

# wrong code:
@is_ok.expression
def is_ok(self):
    return self.status > 30 and self.status < 90

# correct code:
from sqlalchemy.sql import and_
@is_ok.expression
def is_ok(self):
    return and_(self.status > 30, self.status < 90).label('is_ok')

【问题讨论】:

  • 太棒了。将您的解决方案添加为答案并接受它以获得良好的知识库。
  • 我认为您的.expression 是关键。 :)
  • 小心错字:“@is_ok.expressoin”

标签: sqlalchemy


【解决方案1】:

添加自定义表达式。下面使用CASE 语句,但如果您的数据库支持,您也可以使用IF:

@is_ok.expression
def is_ok(cls):
    return case([(cls.status > 0, True)], else_=False).label("is_ok")

更多信息请参见Defining Expression Behavior Distinct from Attribute Behavior 文档。

【讨论】:

  • 如果我使用self.status &gt;= 30,它会很顺利。但如果我使用self.status &gt;= 30 and self.status &lt; 90,它会提高。有什么区别?
  • 但是如果数据在实例级别呢?就像我的混合属性正在使用另一个混合属性来定义它的值。现在进入类级别会为我返回所有混合属性,而不是独立实例的混合属性(如 self)。
  • @MattSom,你需要两个:实例属性和表达式。只有在简单的情况下,sqlalchemy 才能在没有明确定义的情况下找出表达式,但是对于更复杂的事情(比如你最近的问题:stackoverflow.com/q/67489770/99594),你需要有一个与属性定义相对应的明确定义的表达式。所以有两种不同的“实现”。
  • 那么在这种情况下,我必须再次重新实现 used 和 'main' 混合属性逻辑?就像我的第一个 HP 使用 group by 并且在第二个中使用。现在对于我在第二个 HP 中的表达式,我需要为第一个 HP 再次定义一个分组实体,以便我可以重建我的逻辑?这意味着如果我的混合属性使用大量其他混合属性,则最后一个的表达式总是重做工作。或者我应该为每个 HP 创建一个类级别的表达式并以相同的方式使用它们?
  • 我可能在这里误解了你原来的问题。不,您不需要从头开始重新实现所有内容,您绝对可以重用您的实现,sqlalchemy 会正确组合它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
相关资源
最近更新 更多