我有一个函数检查对象的某些属性,并根据结果返回布尔值。在过滤器中编写它太复杂了,但它起作用并返回正确的值。
现在我想使用sqlalchemy返回此函数返回True的所有对象。我试过了:
DBSession.query(MyObject).filter(self.check_attributes(MyObject) == True).all()
和
DBSession.query(MyObject).filter(self.check_attributes(MyObject)).all()
两者都未能选择正确的对象。我做错了什么?
答案 0 :(得分:13)
正如我在评论中所说,hybrid_method
/ hybrid_property
是适合您用例的模式。它可能起初看起来很复杂,但实际上很简单。该函数的第一个版本与Python方法或属性完全相同,第二个版本充当类方法。 SQLAlchemy过滤器在类上工作以生成SQL。
这只是一个无用的示例,但您的示例可能会有一个复杂的计算而不是therabouts
。
如果不需要传递任何参数,我建议改为使用hybrid_property
。
class MyObject(Model):
name = Column(String)
num = Column(Integer)
@hybrid_method
def therabouts(self, n):
return self.num > n - 5 and self.num <= n + 5
@therabouts.expression
def therabouts(cls, n):
return and_(cls.num > n - 5, cls.num <= n + 5)
@hybrid_property
def is_al(self):
return self.name.lower().startswith('al')
@is_al.expression
def is_al(cls):
return cls.name.ilike('al%')
# When used as a class method @thereabouts.expression is called
near20 = session.query(MyObject).filter(MyObject.therabouts(20)).first()
# When used as an instance, @hybrid_method is called
near20.therabouts(20) # True
near20.therabouts(22) # Maybe True
near20.therabouts(50) # False
# filter example (class)
all_als = session.query(MyObject).filter(MyObject.is_al).all()
for al in all_als:
print al.name
# output Alan, Alanzo, Albert...
# instance example (self)
bob = MyObject(name='Robert')
print bob.is_al # False
答案 1 :(得分:1)
如果通过&#34;使用功能&#34;你的意思是在函数内部编写过滤器,你当然可以 - 你只需要将正确的参数传递给它(查询)并在适当的地方使用它的返回(过滤后的查询)
让我们以SQLAlchemy的教程为例:
wendy = session.query(User).filter_by(name='wendy').one()
您可以轻松地将过滤器移动到某个功能:
def my_filter(query):
return query.filter_by(name='wendy')
wendy = my_filter(session.query(User)).one()
然而,如果通过&#34;检查对象是否有某些属性的函数,并根据结果返回布尔值&#34;你的意思是一个接受数据库记录作为参数的函数,我不认为它可以完成(不破坏使用SQL的整个目的)。
- 编辑 - 正如doog abides
指出的那样,hybrid
扩展程序在不对数据库记录进行操作的情况下,会为许多实际操作提供相同的功能目的。
当然,有些人会坚持写下这样的话:
all_users = session.query(User).all()
wendy= filter( lambda u:u.name=='wendy', all_users )
但是,为了您的程序员和用户的理智,请不要这样做。