5

I have list of querysets (all for same model):

results = Entry.objects.all()
result_elms = []
if city_list:
    for city in city_list:
    result_elms.append(results.filter(address__city__icontains=city))

if county_list:
    for county in county_list:
        results_elms.append(results.filter(address__county__icontains=county))
#other filters here, daynamically created

#how can I combine all results_elms (querysets) into one?

I know that I can use | operator to combine querysets from same model. But how can I apply it for all elements from result_elms list?

4
  • There's not enough detail in your question to give an answer. You should provide enough info for someone else to reproduce the problem, and a clear description of the result you're looking for (also the if statement is not needed). Commented Nov 11, 2017 at 10:08
  • Have you tried it using __in? That should help you. See more here Commented Nov 11, 2017 at 10:10
  • @thebjorn what do you mean? My exact question is how can I apply | (combine oparator) for all querysets in list. what other information should I provide? Commented Nov 11, 2017 at 10:28
  • Please specify what other filters you want to apply. What is the expected results? Commented Nov 11, 2017 at 10:34

3 Answers 3

6

You can use Q objects:

from django.db.models import Q

results = Entry.objects.all()
q = Q()
for city in city_list:
    q = q | Q(address__city__icontains=city)
results.filter(q)

The documentation (https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q) has more details and examples.

Sign up to request clarification or add additional context in comments.

6 Comments

The little bit of extra info made it clear what you needed - happy to help :-)
Why q = Q() then q = q | Q(address__city__icontains=city)?
@ammarx because q needs an initial value. It may be clearer if one writes q |= Q(...)? I suppose you could initialize it with the first item in the list q = Q(address__city__icontains=citi_list[0]) and then iterate over city_list[1:] -- but then you need to add back the if statement (instead of letting the for-loop skip the empty list).
You can use results.filter(Q(address__city__icontains=city) | Q(another_filter)) as specified here
@ammarx I've checked and you can use (in my case): q = Entry.objects.empty() :)
|
0

If you are using at least Django 1.11, this is a one liner.

final_results = result_elms[0].union(*result_elms[1:])

here is the link to documentaion. You may refer to my blog post for more examples.

Comments

0

If you are using at least Django 3.2, this looks like

>>> qs1 = Author.objects.values_list('name')
>>> qs2 = Entry.objects.values_list('headline')
>>> qs1.union(qs2).order_by('name')

here is the link to documentation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.