在 Django 中按多个筛选器进行筛选,检查特定条件

66 阅读2分钟

在 Django 中,我们需要根据多种条件进行筛选查询,并希望能够根据某些条件进行 OR 查询。

a21da0c9cc41827eba9fd6b106c73e7.png 例如,我们有以下几个字段:

name
age
mobile
email
address
city

我们需要根据这些字段进行筛选,并希望能够根据以下条件进行 OR 查询:

  • 如果年龄字段是一个数字,则根据年龄进行筛选。
  • 根据手机号码进行筛选。
  • 根据电子邮件地址进行筛选。
  • 根据地址进行筛选。
  • 根据城市进行筛选。

但是,我们在尝试实现这个功能时遇到了问题。

def or_q_if_truthfull(**kwargs):
    filtered = [Q(**{k: v}) for k, v in kwargs.items() if v]
    http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
    if filtered:
        return reduce(or_,filtered)
    else:
        return Q()

def check():        
    if age.isdigit():
        my_q = or_q_if_truthfull(
            name__lower__contains=name.lower(),
            age=age,
            mobile__contains=phone,
            email__lower__contains=email.lower(),
            address__lower__contains=address.lower(),
            city__lower__contains=city.lower(),
        )
    else:
        my_q = or_q_if_truthfull(
            name__lower__contains=name.lower(),
            mobile__contains=phone,
            email__lower__contains=email.lower(),
            address__lower__contains=address.lower(),
            city__lower__contains=city.lower(),
        )

我们希望能够将 if 和 else 块合并为一个块。

Method 1:
my_q = or_q_if_truthfull(
    name__lower__contains=name.lower(),
    age=age if age.isdigit(),
    mobile__contains=mobile,
    alternate__contains=alternate,
    email__lower__contains=email.lower() if email else email,
    address__lower__contains=address.lower(),
    city__lower__contains=city.lower(),
)

File "/home/joel/myappointments/clinic/views.py", line 97
age=age if age.isdigit(),
                        ^
SyntaxError: invalid syntax

Then I tried this:
Method 2:
from numbers import Number
my_q = or_q_if_truthfull(
    cstid=HospitalID,
    name__lower__contains=name.lower() if name else name,
    age=age if isinstance(age, Number),
    mobile__contains=mobile,
    alternate__contains=alternate,
    email__lower__contains=email.lower() if email else email,
    address__lower__contains=address.lower(),
    city__lower__contains=city.lower(),
)

File "/home/joel/myappointments/clinic/views.py", line 97
    age=age if isinstance(age, Number),
                                    ^
SyntaxError: invalid syntax

What's the issue in the two methods I tried? Can you suggest a minimalistic solution?

2、解决方案

问题在于,在 Python 中,如果变量不持有任何值,则需要使用 None 关键字。

对于合并查询条件,可以采用以下代码:

my_q = or_q_if_truthfull(
    name__lower__contains=name.lower(),
    age=age if age.isdigit() else None,
    mobile__contains=phone,
    email__lower__contains=email.lower(),
    address__lower__contains=address.lower(),
    city__lower__contains=city.lower(),
)

这样,我们就能够将 if 和 else 块合并为一个块,并且能够根据指定的条件进行 OR 查询。