[Solved]-Display Multiple Queryset in List View

2πŸ‘

βœ…

the way i did it was using itertools chain and attrgetter

from itertools import chain
from operator import attrgetter

class MyListView(ListView):
    template_name = 'list.html'
    def get_queryset(self):
        qs1 = Events.objects.all() #your first qs
        qs2 = Marks.objects.all()  #your second qs
        #you can add as many qs as you want
        queryset = sorted(chain(qs1,qs2),key=attrgetter('timestamp'),)
        return queryset

got the answer from this post Combine 2 Django Querysets from Different Models

edit

#models.py
class Events(models.Model):
    ...
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True,)

class Marks(models.Model):

    ...
    timestamp = models.DateTimeField(auto_now=False, auto_now_add=True,)


#templates
 {% for item in queryset %}
 {% if item.anyfieldusniquetoqs1 %}
   #here goes all qs1 field you want to display
 {% else %}
   #here goes all qs2 field you want to display
 {% endfor %}
πŸ‘€LeLouch

16πŸ‘

Though not related to the core question, but since this answer shows up because of the title, so i am posting this for newbies:

To return multiple querysets form a single ListView, if you can combine all the querysets in a single variable then it becomes acceptable in Django. The simple method would be to use a dict.

For eg: I need to fetch two queries from same Model, one is all the sellers and the other is top 5 sellers.
So in views.py:

class ViewName(ListView):
    model = ModelName
    template_name = "seller_info.html"
    context_object_name = 'sellers'

    def get_queryset(self):
        queryset = {'all_sellers': ModelName.objects.all(), 
                    'top_seller': ModelName.objects.all().filter(is_highest=True)[:5]}
        return queryset

In seller_info.html you can access each of these querysets by:

For displaying all sellers:

{% if sellers %}
    {% for seller in sellers.all_sellers %}
      <p> {{ seller.name }} </p>
    {% endfor %}
{% endif %}

For displaying top_seller:

{% if sellers.top_seller %}
    {% for seller in sellers.top_seller %}
      <p> {{ seller.name }} </p>
    {% endfor %}
{% endif %}

Please note that if there is only one top seller then also use the above format of html but modify the queryset like: 'top_seller': ModelName.objects.all().filter(is_highest=True)[:1]

4πŸ‘

You could possibly zip all the querysets together. So if you override get_context_data and then say you had variables events and marks which contain a events querset and marks queryset, you could store those into one context variable. Then in the template you could put everything in a table and have a separate column for events and marks. This will put everything in order by their date, but they will just be in separate columns.

Views.py

class MyClass(ListView):
    get_context_data(self,**kwargs):
        context = super().get_context_data(**kwargs)
        events = Events.objects.all().order_by('-date')
        marks = Marks.objects.all().order_by('-date')
        context['group'] = zip(events,marks)
        return context

template

<table class="table">
    <thead class="thead">
        <tr>
            <th>Events</th>
            <th>Marks</th>
        </tr>
    </thead>
    <tbody>
        {% for events,marks in group %}
            <td>{{ events }}</td>
            <td>{{ marks }}</td>
        {% endfor %}
    </tbody>
</table>

Leave a comment