Django Pass Multiple Models to one Template

47,112

Solution 1

I suggest you remove your object_list view,

define a dictionary for this specific view,

   all_models_dict = {
        "template_name": "contacts/index.html",
        "queryset": Individual.objects.all(),
        "extra_context" : {"role_list" : Role.objects.all(),
                           "venue_list": Venue.objects.all(),
                           #and so on for all the desired models...
                           }
    }

and then in your urls:

#add this import to the top  
from django.views.generic import list_detail

(r'^$', list_detail.object_list, all_models_dict),

Solution 2

I ended up modifying @thikonom 's answer to use class-based views:

class IndexView(ListView):
    context_object_name = 'home_list'    
    template_name = 'contacts/index.html'
    queryset = Individual.objects.all()

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        context['roles'] = Role.objects.all()
        context['venue_list'] = Venue.objects.all()
        context['festival_list'] = Festival.objects.all()
        # And so on for more models
        return context

and in my urls.py

url(r'^$', 
    IndexView.as_view(),
    name="home_list"
        ),

Solution 3

If you want to build it on Django 1.5 you will be able to utilize stable version of CBVs. Please find code below.

Great doc you can find here https://docs.djangoproject.com/en/dev/topics/class-based-views/mixins/

class ProductsCategoryList(ListView):
    context_object_name = 'products_list'
    template_name = 'gallery/index_newborn.html'

    def get_queryset(self):
        self.category = get_object_or_404(Category, name=self.args[0])
        return Products.objects.filter(category=self.category)

    def get_context_data(self, **kwargs):
        kwargs['category'] = Category.objects.all()
        # And so on for more models
        return super(ProductsCategoryList, self).get_context_data(**kwargs)
Share:
47,112
Nahanaeli Schelling
Author by

Nahanaeli Schelling

Updated on July 09, 2022

Comments

  • Nahanaeli Schelling
    Nahanaeli Schelling almost 2 years

    I am building an address book that includes the relationships between entries, etc. I have separate models for Individuals, Companies, Venues, and Roles. On my index page I would like to list all of the instances of each model and then filter them. So that a person could easily search and find an entry. I have been able to list a single model using generic views and use get_extra_context to show one more model:

    #views.py
    
     class IndividualListView(ListView):
    
        context_object_name = "individual_list"
        queryset = Individual.objects.all()
        template_name='contacts/individuals/individual_list.html'
    
    
    class IndividualDetailView(DetailView):
    
        context_object_name = 'individual_detail'
        queryset = Individual.objects.all()
        template_name='contacts/individuals/individual_details.html'
    
        def get_context_data(self, **kwargs):
            context = super(IndividualDetailView, self).get_context_data(**kwargs)
            context['role'] = Role.objects.all()
            return context
    

    I am also able to list a single model using a custom view:

    #views.py
    def object_list(request, model):
        obj_list = model.objects.all()
        template_name = 'contacts/index.html'
        return render_to_response(template_name, {'object_list': obj_list}) 
    

    Here are the urls.py for both of these tests:

    (r'^$', views.object_list, {'model' : models.Individual}),
    
    (r'^individuals/$', 
        IndividualListView.as_view(),
            ),
    (r'^individuals/(?P<pk>\d+)/$',
        IndividualDetailView.as_view(),
    
             ),
    

    So my question is "How do I modify this to pass more then one model to the template?" Is it even possible? All of the similar questions on StackOverflow only ask about two models (which can be solved using get_extra_context).

  • Nahanaeli Schelling
    Nahanaeli Schelling over 11 years
    Thank you! This is exactly what I needed.
  • Brandon Bertelsen
    Brandon Bertelsen over 11 years
    +1 it was surprisingly difficult to find this information. Thanks!
  • noobes
    noobes about 11 years
    hi @Nahanaeli can i ask what will the template look like when you have two models?
  • KhoPhi
    KhoPhi about 10 years
    I think its just overkill
  • grillazz
    grillazz about 10 years
    Sorry but I can see nothing overkilling it ;)
  • AlanSE
    AlanSE almost 9 years
    Great answer. Might I ask, what if you need to get information passed by the url parser at the same time? Say we were taking in the individual's primary key (as in the question), and we needed to use this to filter the venue list. I'm unsure how the method get_context_data could receive that identifier.
  • Tim S.
    Tim S. over 8 years
    Great answer, exactly what I was looking for... +1!
  • kevr
    kevr over 7 years
    I wish there was some actual explanation.
  • chris Frisina
    chris Frisina almost 6 years
    @noobes it looks just like the value of the key[value] dictionary, so just access it via for role in roles or for venue in venue_list
  • Kilzrus
    Kilzrus over 5 years
    @chrisFrisina How would this look in the template? my template seems to show all of the venue_list in this case, rather than just the venue list which is associated with the chosen individual (i.e My page is loaded from the pk of individual and i only want to show what venues this individual is assigned to)
  • Ashish Kumar
    Ashish Kumar over 3 years
    @noobes how do we pass current instance of a model?