I have a form that has a group of 13 checkboxes that together make up my search criteria... except that I also added a pair of radio buttons for ALL or ANY.
I was hoping to get away with something elegant like:
priority_ids = request.GET.getlist("priority") # checkboxes
collection = request.GET.get("collection") # radio buttons
priorities = []
for priority_id in priority_ids:
priorities.append(Q(focus__priority=priority_id))
if (collection == "any"): qset = any(priorities)
elif (collection == "all"): qset = all(priorities)
However, any() and all() return a boolean, not a queryset that I can use in a filter. I want an "any" or "all" that does the equivalent of "Q(...) | Q(...) | Q(...)" or "Q(...) & Q(...) & Q(...)" for anywhere from 1 to 13 criteria.
There's nothing that Django needs to do about that. You just need to combine your Q
-s with &
and respectively |
, in a simple loop or in a more compact way with reduce
.
And regarding terminology it seems to me that you are calling Q
a queryset, but it's not. It's a filter on a queryset.
Something like the below should work:
priority_ids = request.GET.getlist("priority")
collection = request.GET.get("collection")
priority_filters = []
for priority_id in priority_ids:
priority_filters.append(Q(focus__priority=priority_id))
base_qs = SomeModel.objects.all()
if collection == "any":
filtered_qset = base_qs.filter(reduce(operator.or_, priority_filters))
elif collection == "all":
filtered_qset = base_qs.filter(reduce(operator.and_, priority_filters))
priority_filters = [Q(focus__priority=p_id) for p_id in priority_ids]
: - Dougal 2012-04-07 18:46
any
case could probably be handled by using an __in
lookup type (SomeModel.objects.filter(focus__priority__in=priority_ids)
). I think you have to do it this way for all
- Dougal 2012-04-07 18:50
lambda
s can be replaced byoperator.or_
andoperator.and_
, respectively - Dougal 2012-04-06 20:05