Q:

Django loop is returning multiple posts

I am trying to get django to display posts from a single catgory on that category's page, instead, it displays all the categories and the posts under each category in the template. 
Here are my models (I trimmed them down):
class Category(models. Model):
    ...
    title = models. CharField(max_length=255, verbose_name="Title", null=True, blank=True)
    slug = models. SlugField(max_length=200, unique=True)

class Petition(models. Model):
    ...
    category = models. ManyToManyField(Category, verbose_name="Category", related_name='petitions')
    ...

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

class CategoryView(CategoryMixin, generic. ListView):
    model = Category
    categories = Category.objects.all() # this will get all categories, you can do some filtering if you need (e.g. excluding categories without posts in it)
    queryset = Category.objects.all()
    template_name = 'petition/category_list.html'

class CategoryIndexView(generic. ListView):
    model = Category
    template_name = 'petition/category.html'
    context_object_name = 'category_list'

    def get_queryset(self): 
        return Category.objects.prefetch_related('petitions').order_by('-created_on')[:10]

class PetitionIndexView(generic. ListView):
    template_name = 'petition/home.html'
    context_object_name = 'petition_list'
    queryset = Petition.objects.order_by('-created_on')

    def get_queryset(self):
        queryset_list = Petition.objects.order_by('-created_on')

        #SEARCH QUERY LOGIC
        query = self.request. GET.get("q")
        if query:
            queryset_list = queryset_list.filter(
                Q(title__icontains = query) |
                Q(petition__icontains = query) |
                Q(created_by__first_name__icontains = query) | #icontains = only text fields.  Use text field within foreign key field
                Q(created_by__last_name__icontains = query) 
                ).distinct()

        paginator = Paginator(queryset_list, 10) # Show 10 posts per page
        page = self.request. GET.get('page')

        try:
            queryset = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page. 
            queryset = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results. 
            queryset = paginator.page(paginator.num_pages)

        return queryset

        context = {
        'object_list' : queryset,
        'title' : 'List'
        }

urls.py:
url(r'^$',views. PetitionIndexView.as_view(), name="homepage"),
url(r'^petition/(?P<slug>[\w-]+)/$',views. DetailView.as_view(), name="detail"),
url(r'^categories/$', views. CategoryView.as_view(), name='category_list'),
url(r'^category/(?P<slug>[\w-]+)/$',views. CategoryIndexView.as_view(), name="category_detail"),

And my template (category.html for the CategoryIndexView) is in this format,
category.html:
{% for category in category_list %}
    {% for petition in category.petitions.all %}
        ...
        {{ petition.title }}
        ...
    {% end for %}
{% end for %}

This shows posts in Category A, B and C in the same template. 
With the views I set, how can I get it to show only posts for category A when category A is clicked? 
Also, the ordering is not working properly.  It is not adhering to the ordering I gave it in the view

A:

You're using the wrong view class.  A ListView is to show a list of instances of the class; so a CategoryIndexView would be to show the list of categories.  But you don't want a list of categories; you want a single category, along with a list of its petitions.  So, you should use a DetailView. 
class CategoryDetailView(generic. DetailView):
    model = Category
    template_name = 'petition/category.html'
    context_object_name = 'category'

    def get_queryset(self): 
        return Category.objects.prefetch_related('petitions')

And the template is just:
{% for petition in category.petitions.all %}
    ...
    {{ petition.title }}
    ...
{% end for %}

Edit: I changed the context_object_name from 'category_list' to 'category' and the template is returning the right posts now.