How to combine two or more querysets in a Django view

0 votes

I'm trying to build the search for a Django site I am building, and in that search, I am searching in 3 different models. And to get pagination on the search result list, I would like to use a generic object_list view to display the results. But to do that, I have to merge 3 querysets into one.

How can I do that? I've tried this:

result_list = []            
page_list = Page.objects.filter(
    Q(title__icontains=cleaned_search_term) | 
    Q(body__icontains=cleaned_search_term))
article_list = Article.objects.filter(
    Q(title__icontains=cleaned_search_term) | 
    Q(body__icontains=cleaned_search_term) | 
    Q(tags__icontains=cleaned_search_term))
post_list = Post.objects.filter(
    Q(title__icontains=cleaned_search_term) | 
    Q(body__icontains=cleaned_search_term) | 
    Q(tags__icontains=cleaned_search_term))

for x in page_list:
    result_list.append(x)
for x in article_list:
    result_list.append(x)
for x in post_list:
    result_list.append(x)

return object_list(
    request, 
    queryset=result_list, 
    template_object_name='result',
    paginate_by=10, 
    extra_context={
        'search_term': search_term},
    template_name="search/result_list.html")

But this doesn't work. I get an error when I try to use that list in the generic view. The list is missing the clone attribute.

Does anybody know how I can merge the three lists, page_list, article_list and post_list?

Aug 3, 2020 in Python by kartik
• 37,490 points
1,617 views

1 answer to this question.

0 votes

Hello @kartik,

Concatenating the querysets into a list is the simplest approach. If the database will be hit for all querysets anyway (e.g. because the result needs to be sorted), this won't add further cost.

from itertools import chain
result_list = list(chain(page_list, article_list, post_list))

Using itertools.chain is faster than looping each list and appending elements one by one, since itertools is implemented in C. It also consumes less memory than converting each queryset into a list before concatenating.

Now it's possible to sort the resulting list e.g. by date . The sorted() function conveniently accepts a generator and returns a list:

result_list = sorted(
    chain(page_list, article_list, post_list),
    key=lambda instance: instance.date_created)

If you're using Python 2.4 or later, you can use attrgetter instead of a lambda.

from operator import attrgetter
result_list = sorted(
    chain(page_list, article_list, post_list),
    key=attrgetter('date_created'))

Hope this is helpfull!!

Thank You!

answered Aug 3, 2020 by Niroj
• 82,580 points

Related Questions In Python

0 votes
1 answer
0 votes
1 answer

How do I use urllib to see if a website is 404 or 200 in Python?

For Python 3, try doing this: import urllib.request, ...READ MORE

answered Nov 29, 2018 in Python by Nymeria
• 3,520 points

edited Dec 11, 2018 by Nymeria 7,616 views
0 votes
1 answer

How to merge two dictionaries in a single expression?

In Python 3.5 or greater: z = {**x, ...READ MORE

answered Mar 12, 2019 in Python by Trisha
115 views
0 votes
2 answers

How can I write a program to add two numbers using functions in python?

there is sum() function as a built ...READ MORE

answered Oct 24, 2020 in Python by anonymous
13,014 views
0 votes
1 answer

How to temporarily disable a foreign key constraint in MySQL?

Hello @kartik, To turn off foreign key constraint ...READ MORE

answered Jun 23, 2020 in Python by Niroj
• 82,580 points
617 views
0 votes
1 answer

How do I use Django templates without the rest of Django?

Hello @kartik, Let's say you have this important ...READ MORE

answered Jun 23, 2020 in Python by Niroj
• 82,580 points
255 views
0 votes
1 answer

How to load a custom JS file in Django admin home?

Hello @kartik, You can override templates/admin/index.html and add the JavaScript ...READ MORE

answered May 14, 2020 in Python by Niroj
• 82,580 points
2,051 views
0 votes
1 answer

How to check if an element is present in a Django queryset?

Hello @kartik, You can use the following code: if ...READ MORE

answered May 27, 2020 in Python by Niroj
• 82,580 points
3,874 views