2017-03-08 1 views
5

J'ai une base de données « Nouvelles » créée par SQLAlchemy:valeur SQLAlchemy booléenne de cette clause n'est pas définie

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) 

J'ai aussi une fonction f (titre), qui obtient une chaîne et renvoie l'une des 3 variantes des chaînes: 'bon', 'peut-être' ou 'jamais'. J'essaie d'obtenir les lignes filtrées:

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

Mais le programme ne réussit pas, soulevant cette erreur:

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

Comment puis-je resovle il?

+0

@ IljaEverilä Vous devriez poster que comme une réponse, j'ai presque raté votre commentaire et déjà en train d'écrire la était même chose. –

+0

J'essayais de trouver une copie existante pour cela, mais à la grande surprise ne pouvait pas. –

Répondre

9

Le problème est le suivant:

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

Python ne permet pas surchargeons le comportement booléennes opérationsand et or. Vous pouvez les influencer dans une certaine mesure avec __bool__ dans Python 3 et __nonzero__ dans Python 2, mais tout ce qu'il fait est .

Si les objets en question n'a pas mis en œuvre __bool__ et jeté l'erreur, vous auriez eu des erreurs peut-être plutôt énigmatiques en raison de la 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 

parce

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

Cela pourrait et conduirait à tirer les cheveux sous la forme d'expressions SQL incorrectes:

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

Pour produire des expressions booléennes SQL soit utiliser les and_(), or_() et not_() fonctions d'expression sql, ou & binaire, | et ~ surcharge de l'opérateur:

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

ou

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

ou passer plusieurs critère à un appel à Query.filter():

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

ou combiner plusieurs appels à filter():

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