Reputation: 611
i'm trying to display multiple queryset with multiple models as a timeline and sort em by time instead of displaying one queryset after the other my current code looks like that :
<div class="user-info col-md-8">
{% for obj in user.marks_set.all %}
<p>{{ obj.module }}</p>
<p>{{ obj.grade }}</p>
<p>{{ obj.date }}</p>
{% endfor %}
{% for obj in events %}
{{ obj.content }}
{% endfor %}
</div>
all models have date field , i'm trying to display everything and order em by date instead of displaying all marks and after that all events
Upvotes: 11
Views: 8727
Reputation: 611
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
#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 %}
Upvotes: 2
Reputation: 1003
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]
Upvotes: 16
Reputation: 551
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>
Upvotes: 4