SQLAlchemy Boolean value of this clause is not defined

匿名 (未验证) 提交于 2019-12-03 08:30:34

问题:

I have a database "News" created via 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) 

I also have a function f(title), that gets a string and returns one of 3 variants of strings: 'good', 'maybe' or 'never'. I try to get filtered rows:

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

But program fails, raising this error:

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

How can I resovle it?

回答1:

The problem is this:

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

Python does not allow overriding the behaviour of boolean operations and and or. You can influence them to some extent with __bool__ in Python 3 and __nonzero__ in Python 2, but all that does is that it defines the truth value of your object.

If the objects in question had not implemented __bool__ and thrown the error, you would've gotten possibly rather cryptic errors due to the short-circuiting nature of and and or:

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

because

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

This could and would lead to hair pulling in the form of incorrect SQL expressions:

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

To produce boolean SQL expressions either use the and_(), or_(), and not_() sql expression functions, or the binary &, |, and ~ operator overloads:

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

or

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

or pass multiple criterion to a call to Query.filter():

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

or combine multiple calls to filter():

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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!