我如何构造一个复杂的 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 时才有效。
假设我有三个 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 时才有效。