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?