SQLAlchemy:使用`和`和`或`时出现意外结果

时间:2017-03-08 20:23:52

标签: python sqlalchemy boolean

我有一个数据库"新闻"通过SQLAlchemy创建:

class News(Base):
    __tablename__ = "news"
    id = Column(Integer, primary_key = True)
    title = Column(String)
    author = Column(String)
    url = Column(String)
    comments = Column(Integer)
    points = Column(Integer)
    label = Column(String)

我还有一个函数f(title),它获取一个字符串并返回3个字符串变体之一:' good',' may'或者从未' 我尝试过滤行:

rows = s.query(News).filter(News.label == None and f(News.title)=='good').all()

但程序失败,引发了这个错误:

raise TypeError("Boolean value of this clause is not defined")

我该如何解决?

1 个答案:

答案 0 :(得分:21)

问题在于:

News.label == None and f(News.title) == 'good'
#                  ^^^ here

Python不允许覆盖布尔操作 andor的行为。您可以在Python 3中使用__bool__并在Python 2中使用__nonzero__在某种程度上影响它们,但所有这一切都是defines the truth value of your object

如果有问题的对象没有实现__bool__并抛出错误,或者没有抛出实现,那么由于short-circuiting nature of and and or,你可能会得到相当神秘的错误:

In [19]: (News.label == 'asdf') and True
Out[19]: <sqlalchemy.sql.elements.BinaryExpression object at 0x7f62c416fa58>

In [24]: (News.label == 'asdf') or True
Out[24]: True

,因为

In [26]: bool(News.label == 'asdf')
Out[26]: False

这可能并且会导致以不正确的SQL表达式形式拉动头发:

In [28]: print(News.label == 'asdf' or News.author == 'NOT WHAT YOU EXPECTED')
news.author = :author_1

要生成布尔SQL表达式,请使用and_()or_()not_() sql表达式函数,或二进制&|和{ {3}}运算符重载:

# Parentheses required due to operator precedence
filter((News.label == None) & (f(News.title) == 'good'))

filter(and_(News.label == None, f(News.title) == 'good'))

或将多个条件传递给对~的调用:

filter(News.label == None, f(News.title) == 'good')

或将多个来电合并到filter()

filter(News.label == None).filter(f(News.title) == 'good')