I have a MultipleChoiceField
on a form holding car makes. I want to filter my database of cars to the makes that were checked but this causes a problem. How do I get all the Q(make=...)
statements in dynamically?
How I start: ['value1', 'value2', ...]
How I want to end: Q(col='value1') | Q(col='value2') | ...
I've couple of other methods. I've tried appending querysets for each make and doing it the other way around (doing multiple excludes) but they were both really slow.
Have you tried: Model.objects.filter(make__in=list_of_makes)
?
The list_of_makes is what is returned by the MultipleChoiceField
See the query set reference about the __in
operator.
There was another method provided in #django:
reduce(lambda x,y: x | y, [Q1, Q2, Q3, ...])
Ber's method is great for this instance but if you need to filter on dynamic columns, mapping looks like the next cleanest way.
I tried Oli's answer but it didn't work, even with reduce() since it appears Q objects do not accept dictionaries as argument:
Here's how I had it working:
# These are the fields I want to search with an OR clause
search_fields = ['title__icontains', 'publisher__name__icontains', 'authors__name__icontains']
search = 'search string'
clauses = []
for item in search_fields:
clauses.append(queryset.filter(**{item: search}))
queryset = reduce(lambda x, y: x | y, clauses).distinct()
Check for performance issues since I was only able to test with a small dataset.