44

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).

David Nehme
  • 21,379
  • 8
  • 78
  • 117
Nahanaeli Schelling
  • 1,235
  • 1
  • 12
  • 17
  • How can I access content in 'queryset = Individual.objects.all()' which is the Individual model ? @Nahanaeli Schelling – Jia Jun 02 '22 at 10:10

3 Answers3

70

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"
        ),
Massimo Variolo
  • 4,669
  • 6
  • 38
  • 64
Nahanaeli Schelling
  • 1,235
  • 1
  • 12
  • 17
  • 12
    hi @Nahanaeli can i ask what will the template look like when you have two models? – noobes May 02 '13 at 10:13
  • 1
    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. – AlanSE Jun 18 '15 at 01:54
  • Great answer, exactly what I was looking for... +1! – Tim S. Nov 04 '15 at 18:51
  • 2
    @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` – chris Frisina Jul 16 '18 at 03:48
  • @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) – Kilzrus Jan 25 '19 at 18:13
  • @noobes how do we pass current instance of a model? – Ashish Kumar Sep 03 '20 at 10:43
24

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),
thikonom
  • 4,219
  • 3
  • 26
  • 30
9

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)
as2d3
  • 802
  • 2
  • 10
  • 27
grillazz
  • 527
  • 6
  • 15