首页 > 解决方案 > 有条件地向 SQLAlchemy 查询添加多个过滤器,而无需重复代码

问题描述

我有一个 SQLAlchemy 模型:

class Ticket(db.Model):

 __tablename__ = 'ticket'

 id = db.Column(INTEGER(unsigned=True), primary_key=True, nullable=False,
 autoincrement=True)
 cluster = db.Column(db.VARCHAR(128))

 @classmethod
 def get(cls, cluster=None):
     query = db.session.query(Ticket)

     if cluster is not None:
         query = query.filter(Ticket.cluster==cluster)

     return query.one()

如果我添加一个新列并想扩展该get方法,我必须添加一个if xxx is not None如下所示:

 @classmethod
 def get(cls, cluster=None, user=None):
     query = db.session.query(Ticket)

     if cluster is not None:
         query = query.filter(Ticket.cluster==cluster)
     if user is not None:
         query = query.filter(Ticket.user==user)

     return query.one()

有什么办法可以提高效率吗?如果我的列太多,该get方法将变得如此丑陋。

标签: pythonsqlalchemy

解决方案


与往常一样,如果您不想编写重复的内容,请使用循环:

@classmethod
def get(cls, **kwargs):
    query = db.session.query(Ticket)
    for k, v in kwargs.items():
        query = query.filter(getattr(table, k) == v)
    return query.one()

因为我们不再将cluster=None/设置user=None为默认值(而是取决于调用者未指定的内容,根本不会添加到kwargs),我们不再需要阻止添加空值过滤器:如果用户实际要求搜索None;的值,则 null 值将最终出现在参数列表中 所以这个新代码能够在它发生时兑现这个请求。

如果您希望保留调用约定,cluster可以user按位置传递 和 (但用户无法搜索 的值None),请参阅此答案的初始版本


推荐阅读