Django查询未知数量的多个日期范围


问题内容

我有一个允许用户选择多个年龄段的用户的表格:18-24、25-34、35-44等。当前,如果用户选择了多个选择列表中的前两个字段,查询将返回用户18
-34.如果用户选择18-24岁和35-44岁的年龄段,则该年龄段将包含18-44岁的所有年龄段,但不应包括25-34岁的用户。

您将如何在查询中包括多个范围过滤器而又不知道在选择用户表单之前需要过滤的范围数?

如果您知道用户要过滤的年龄范围的数量,我知道您可以使用Q链接范围查询。

这是我当前的查询:

query = User.objects.filter(
            gender__in=genders,
            created__in=dates,
            data_source__in=sources,
            dob__range=[dob_from, dob_to]
        )

提前致谢。


问题答案:

正如您在问题中所说的,您可以使用Q()对象并将它们组合在一起。您不知道Q()会有多少个对象,这不是问题。生成Q()对象的列表,然后将列表缩小为单个Q()

from operator import or_

# import for Python 3, not required in Python 2
from functools import reduce

ranges = [(18,24), (35, 44)]  # hardcoded as an example, you can dynamically generate this
qs = [Q(dob_range=[dob_from_, dob_to]) for (dob_from_, dob_to) in ranges]
# combine the qs
dob_q = reduce(or_, qs, Q())

query = User.objects.filter(
    dob_q,
    gender__in=genders,
    created__in=dates,
    data_source__in=sources,
)

如果您不熟悉reduceor_,则可以通过遍历列表来获得相同的结果:

qs = [Q(dob_range=[dob_from_, dob_to]) for (dob_from_, dob_to) in ranges]
dob_q = Q()
for q in qs:
    dob_q = dob_q | q