tags:

views:

413

answers:

2

In my case, I have a number of column names coming from a form. I want to filter to make sure they're all true. Here's how I currently do it:

for op in self.cleaned_data['options']:
    cars = cars.filter((op, True))

Now it works but there are are a possible ~40 columns to be tested and it therefore doesn't appear very efficient to keep querying.

Is there a way I can condense this into one filter query?

+8  A: 

Build the query as a dictionary and use the ** operator to unpack the options as keyword arguments to the filter method.

op_kwargs = {}
for op in self.cleaned_data['options']:
    op_kwargs[op] = True
cars = CarModel.objects.filter(**op_kwargs)

This is covered in the django documentation and has been covered on SO as well.

Prairiedogg
+2  A: 

Django's query sets are lazy, so what you're currently doing is actually pretty efficient. The database won't be hit until you try to access one of the fields in the QuerySet... assuming, that is, that you didn't edit out some code, and it is effectively like this:

cars = CarModel.objects.all()
for op in self.cleaned_data['options']:
    cars = cars.filter((op, True))

More information here.

Daniel
It's pretty efficient (doesn't hit the database repeatedly), but it still results in cloning the queryset repeatedly, so Prairie Dogg's solution (build up a dictionary and pass it in as kwargs) will be somewhat faster.
Carl Meyer