How Can I Display Multiple Models In a Django ListView?

Question:

I am trying to display several models via a ListView. After some research…I have determined that I can do something like…

class MultiModelListView(LoginRequiredMixin,ListView):
    model = MultiModel 
    context_object_name = 'thing_list'
    template_name = 'view_my_list.html'
    paginate_by = 15

def get_context_data(self, **kwargs):
    context = super(MultiModelListView, self).get_context_data(**kwargs)
    list1 = Model1.objects.filter(created_by=self.request.user)
    list2 = Model2.objects.filter(created_by=self.request.user)
    list3 = Model3.objects.filter(created_by=self.request.user)
    context['list1'] = list1
    context['list2'] = list2
    context['list3'] = list3
    return context

And then in my template….loop over each list….

{% for thing in list1 %}
   Show thing
{% endfor %}

{% for thing in list2 %}
  Show thing 
{% endfor %}

{% for thing in list3 %}
  Show thing
{% endfor %}

This would work…except I really want to co-mingle the events and sort them by creation date which all of the models have….I really want to do an order by for all of the event…not by list per se…Is there a straightforward way to do this….Or do I need to create a "Master" model that has all of these models defined in order to achieve my goal?

Asked By: Steve Smith

||

Answers:

You can join QuerySet objects if you change them into lists. Then sort it with lambda. Assuming, that you want to sort by created_at attribute:

def get_context_data(self, **kwargs):
    context = super(MultiModelListView, self).get_context_data(**kwargs)
    list1 = list(Model1.objects.filter(created_by=self.request.user))
    list2 = list(Model2.objects.filter(created_by=self.request.user))
    list3 = list(Model3.objects.filter(created_by=self.request.user))
    list_all = list1 + list2 + list3
    context["list_all"] = sorted(list_all, key=lambda x: x.created_at)
    return context

You can always use reverse=True in sorted function if you need change orientation.

Answered By: NixonSparrow