【问题标题】:sqlalchemy - elegant way to deal with several optional filters?sqlalchemy - 处理几个可选过滤器的优雅方式?
【发布时间】:2015-03-04 19:41:15
【问题描述】:

假设我有一个带有多个 可选 过滤器的查询方法。我想要实现的是,如果我将一些非 None 值传递给过滤参数然后进行过滤,如果过滤值是 None,则忽略它。

def get_query_results(filter1=None, filter2=None, ...):
    res = models.Item.query
    if filter1 is not None:
        res = res.filter(filter1=filter1)
    if filter2 is not None:
        res = res.filter(filter2=filter2)
    ....
    return res.all()

我要避免的是模式

if XXX:
    res.filter(XXX=XXX)

我想知道是否有更优雅的方式来实现这一点?

例如,将各种过滤器作为参数传递?

或者,当过滤器值为None时,我们可以做一些魔术来省略过滤器?

【问题讨论】:

    标签: python mysql coding-style sqlalchemy


    【解决方案1】:

    与您显示的代码完全等效的代码是:

    def get_query_results(*filters):
        res = models.Item.query
        for i, filt in enumerate(filters, 1):
            if filt is not None:
                d = {'filter{}'.format(i): filt}
                res = res.filter(**d)
        return res.all()
    

    我不太确定为什么您需要 res.filter 的命名参数具体为 filter1filter2 等,但是这个 sn-p 将在没有您可以理解的重复模式的情况下做到这一点.

    如果名称实际上是filter1filter2等,只要知道所需的名称就可以了:

    NAMES = 'foo bar baz bat'.split()
    
    def get_query_results(*filters):
        res = models.Item.query
        for name, filt in zip(NAMES, filters):
            if filt is not None:
                d = {name: filt}
                res = res.filter(**d)
        return res.all()
    

    这种变体适用于这种情况。

    【讨论】:

    • 请原谅一个幼稚的问题,请确认这里发生的事情是,您正在构建一个最终在运行 .all() 方法时执行的查询。我只是想确保这段代码不会在查询中获取整个表格内容,然后在后续步骤中过滤掉内容,谢谢。
    猜你喜欢
    • 2021-04-04
    • 1970-01-01
    • 2018-02-02
    • 2015-04-10
    • 2011-08-01
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多