python - SQLAlchemy: resultados inesperados al usar `y` y` o`



boolean (1)

El problema es este:

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

Python no permite anular el comportamiento de las operaciones booleanas and y or . Puede influenciarlos hasta cierto punto con __bool__ en Python 3 y __nonzero__ en Python 2, pero todo lo que hace es que define el valor de verdad de su objeto .

Si los objetos en cuestión no hubieran implementado __bool__ y __bool__ arrojado el error, o la implementación no hubiera arrojado, posiblemente hubieras cometido errores crípticos debido a la naturaleza de cortocircuito de 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

porque

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

Esto podría y llevaría a que el cabello se arrastre en forma de expresiones SQL incorrectas:

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

Para producir expresiones SQL booleanas, use las and_() expresión and_() , or_() , y not_() sql, o el binario & , | , y ~ sobrecargas del operador:

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

o

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

o pasar múltiples criterios a una llamada a Query.filter() :

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

o combinar varias llamadas para filter() :

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

Tengo una base de datos "Noticias" creada a través de 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)

También tengo una función f(title) , que obtiene una cadena y devuelve una de las 3 variantes de cadenas: 'bueno', 'quizás' o 'nunca'. Intento obtener filas filtradas:

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

Pero el programa falla, provocando este error:

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

¿Cómo puedo resolverlo?





boolean