Looking for Django any() and all() on querysets

Go To StackoverFlow.com

0

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.

2012-04-05 22:29
by Ubuntourist


1

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))
2012-04-05 22:56
by Botond Béres
Note that your lambdas can be replaced by operator.or_ and operator.and_, respectively - Dougal 2012-04-06 20:05
+1, thanks for pointing that ou - Botond Béres 2012-04-07 18:39
While we're at it, might as well do priority_filters = [Q(focus__priority=p_id) for p_id in priority_ids] : - Dougal 2012-04-07 18:46
Also, the 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
Ads