title: Django manager for _set in model
body: <p>I'm in the progress of learning Django at the moment but I can't figure out how to solve this problem on my own. I'm reading the book <em>Developers Library - Python Web Development With Django</em> and in one chapter you build a simple CMS system with two models (Story and Category), some generic and custom views together with templates for the views.</p>
  
  <p>The book only contains code for listing stories, story details and search. I wanted to expand on that and build a page with nested lists for categories and stories.</p>
  
  <pre><code>- Category1
  -- Story1
  -- Story2
  - Category2
  - Story3 etc.
  </code></pre>
  
  <p>I managed to figure out how to add my own generic object_list view for the category listing.  My problem is that the Story model have STATUS_CHOICES if the Story is public or not and a custom manager that'll only fetch the public Stories per default. I can't figure out how to tell my generic Category list view to also use a custom manager and only fetch the public Stories. Everything works except that small problem. I'm able to create a list for all categories with a sub list for all stories in that category on a single page, the only problem is that the list contains non public Stories.</p>
  
  <p>I don't know if I'm on the right track here. My urls.py contains a generic view that fetches all Category objects and in my template I'm using the <em>category.story_set.all</em> to get all Story objects for that category, wich I then loop over.</p>
  
  <p>I think it would be possible to add a if statement in the template and use the VIEWABLE_STATUS from my model file to check if it should be listed or not. The problem with that solution is that it's not very DRY compatible.</p>
  
  <p>Is it possible to add some kind of manager for the Category model too that only will fetch in public Story objects when using the story_set on a category?</p>
  
  <p>Or is this the wrong way to attack my problem?</p>
  
  <p><strong>Related code</strong></p>
  
  <p>urls.py (only category list view):</p>
  
  <pre><code>urlpatterns += patterns('django.views.generic.list_detail',
      url(r'^categories/$', 'object_list', {'queryset': Category.objects.all(),
                                            'template_object_name': 'category'
                                           }, name='cms-categories'),
  </code></pre>
  
  <p>models.py:</p>
  
  <pre><code>from markdown import markdown
  import datetime
  from django.db import models
  from django.db.models import permalink
  from django.contrib.auth.models import User
  
  VIEWABLE_STATUS = [3, 4]
  
  class ViewableManager(models.Manager):
      def get_query_set(self):
          default_queryset = super(ViewableManager, self).get_query_set()
          return default_queryset.filter(status__in=VIEWABLE_STATUS)
  
  class Category(models.Model):
      """A content category"""
      label = models.CharField(blank=True, max_length=50)
      slug = models.SlugField()
  
      class Meta:
          verbose_name_plural = "categories"
  
      def __unicode__(self):
          return self.label
  
      @permalink
      def get_absolute_url(self):
          return ('cms-category', (), {'slug': self.slug})
  
  class Story(models.Model):
      """A hunk of content for our site, generally corresponding to a page"""
  
      STATUS_CHOICES = (
          (1, "Needs Edit"),
          (2, "Needs Approval"),
          (3, "Published"),
          (4, "Archived"),
      )
  
      title = models.CharField(max_length=100)
      slug = models.SlugField()
      category = models.ForeignKey(Category)
      markdown_content = models.TextField()
      html_content = models.TextField(editable=False)
      owner = models.ForeignKey(User)
      status = models.IntegerField(choices=STATUS_CHOICES, default=1)
      created = models.DateTimeField(default=datetime.datetime.now)
      modified = models.DateTimeField(default=datetime.datetime.now)
  
      class Meta:
          ordering = ['modified']
          verbose_name_plural = "stories"
  
      def __unicode__(self):
          return self.title
  
      @permalink
      def get_absolute_url(self):
          return ("cms-story", (), {'slug': self.slug})
  
      def save(self):
          self.html_content = markdown(self.markdown_content)
          self.modified = datetime.datetime.now()
          super(Story, self).save()
  
      admin_objects = models.Manager()
      objects = ViewableManager()
  </code></pre>
  
  <p>category_list.html (related template):</p>
  
  <pre><code>{% extends "cms/base.html" %}
  {% block content %}
      &lt;h1&gt;Categories&lt;/h1&gt;
      {% if category_list %}
          &lt;ul id="category-list"&gt;
          {% for category in category_list %}
              &lt;li&gt;&lt;a href="{{ category.get_absolute_url }}"&gt;{{ category.label }}&lt;/a&gt;&lt;/li&gt;
              {% if category.story_set %}
                  &lt;ul&gt;
                      {% for story in category.story_set.all %}
                          &lt;li&gt;&lt;a href="{{ story.get_absolute_url }}"&gt;{{ story.title }}&lt;/a&gt;&lt;/li&gt;
                      {% endfor %}
                  &lt;/ul&gt;
              {% endif %}
          {% endfor %}
          &lt;/ul&gt;
      {% else %}
          &lt;p&gt;
              Sorry, no categories at the moment.
          &lt;/p&gt;
      {% endif %}
  {% endblock %}
  </code></pre>