我如何构造一个复杂的 Django 查询,有时条件是 ALL

How do I construct a Complex Django Query where sometimes the conditions are ALL

假设我有三个 Choicefields,并且我知道它们在我看来的价值。例如:

    fpriority = filtform["priority"].value()
    fstatus = filtform["status"].value()
    fassigned = filtform["assigned"].value()

每个值都是与 Table 中相应列相关的整数(例如 1-3)。所以我对查询的第一个想法是:

        tasks = Task.objects.filter(Q(priority=fpriority) & Q(
            status=fstatus) & Q(assigned_to=fassigned))
       

但我的问题是,我也想为所有人提供一个选择。所以假设我在每个 ChoiceField 中包含零 (0) 来表示 ALL

所以现在上面的每个 Q 条件都必须包括变量为 0 的可能性,因此对于条件的那部分意味着全部。

有没有想过一个干净的方法来做到这一点?

编辑:下面的评论非常有建设性,但我还没有完全理解。该建议假设如果一个参数为零,则所有参数都为零——事实并非如此。我学到了很多关于 Q 的知识,但还有更多工作要做。我现在已经让我的多过滤器系统工作了,但这是一个糟糕的组合。所以如果可能的话,我希望看到一个更优雅的解决方案。这是完成这项工作的代码:

    fpriority = filtform["priority"].value()
    fstatus = int(filtform["status"].value())
    fassigned = int(filtform["assigned"].value())

    tasklist = get_object_or_404(TaskList, owner=request.user)
    if tasklist:

        if fpriority == "0":  # all priorities
            step1 = Task.objects.all()
        else:
            step1 = Task.objects.filter(priority=fpriority)

        if fstatus == 0:  # all status's
            step2 = step1
        else:
            step2 = step1.filter(status_id=fstatus)

        if fassigned == 0:  # all assigned people
            step3 = step2
        else:
            step3 = step2.filter(assigned_to_id=fassigned)

        tasks = step3
        # tasks = Task.objects.filter(Q(priority=fpriority) & Q(
        #    status=fstatus) & Q(assigned_to=fassigned))

你想要的是这样的:

q = Q()  # or initialize with filter conditions that should apply in any case

if not (fpriority == 0 and fstatus == 0 and fassigned == 0):
    q = q & Q(priority=fpriority) & Q(status=fstatus) & Q(assigned_to=fassigned)

tasks = Task.objects.filter(q)

或过滤器值的类似条件。

编辑:您还可以将单个过滤器设置为 'all':

q = Q()

if fpriority > 0:
    q &= Q(priority=fpriority)

if fstatus > 0:
    q &= Q(status=fstatus)

if fassigned  > 0:
    q &= Q(assigned_to=fassigned)

tasks = Task.objects.filter(q)

每个过滤器只有在过滤器值 > 0 时才有效。