Django dynamic OR queries

2020-07-18 03:22发布

问题:

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.

回答1:

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.



回答2:

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.



回答3:

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.