Search code examples
djangodjango-templatesdjango-generic-viewsdjango-1.6

How to show a category list made by generic views in multiple pages?


I'm trying to build my own Blog app with Django 1.6. I've generated a category list by generic views like this:

urls.py

url(r'^categories/?$', views.ListView.as_view(model=Category), name='categories'),

category_list.html

   <h3>Categories</h3>
   {% for category in object_list %}
     <ul>
       <li>{{ category.title }}</li>
     </ul>
   {% endfor %}

all categories are now listed at /categories.

My problem is when I add it to base.html or index.html file, output changes to article.title not category.title How can I add this Category list to other pages such as Index or Article? Here's my complete views.py file:

views.py

from django.shortcuts import get_object_or_404, render
from django.views.generic import ListView, DetailView

from blog.models import Article, Category

class IndexView(ListView):
    template_name = 'blog/index.html'
    context_object_name = 'latest_article_list'

    def get_queryset(self):
        return Article.objects.order_by('-pub_date')[:10]

class ArticleView(DetailView):
    model = Article
    template_name = 'blog/article.html'

Solution

  • It renders article.title because object_list points into article view context, you cannot include isolated view into another view.

    I think the cleanest way would be to create a mixin class for categories context and add it to each view, that needs to render it.

    Something like this:

    class CategoryMixin(object):
        def get_categories(self):
            return Category.objects.all()
    
        def get_context_data(self, **kwargs):
            context = super(CategoryMixin, self).get_context_data(**kwargs)
            context['categories'] = self.get_categories()
            return context
    

    then add it to the view class:

    class IndexView(CategoryMixin, ListView):
        ...
    

    and also include category_list.html inside each template, passing the context variable (this way you have isolated variable names):

    {% include "category_list.html" with object_list=categories only %}