Django Generic Views: When to use ListView vs. DetailView

user1272534 picture user1272534 · Mar 19, 2012 · Viewed 11k times · Source

I am using Django's class based generic views in a blog application. One of my views displays a list of posts that have a certain tag. I can write this view as a ListView of posts, filtered by tag. Or I can write this view as a DetailView of the tag, and add the relevant posts to the context.

Is one way more proper -- or Pythonic -- than the other?

The ListView approach seems more semantic, because what I want is a list of posts, but it's also slightly more complex. It requires that I overwrite two methods. The DetailView approach only requires me to overwrite one method.

class PostTagView(ListView):
    """Display all blog posts with a given tag."""
    queryset = Post.objects.published()

    def get_context_data(self, **kwargs):
        context = super(PostTagView, self).get_context_data(**kwargs)
        context['tag'] = get_object_or_404(Tag, slug=self.kwargs['slug'])
        return context

    def get_queryset(self, **kwargs):
        queryset = super(PostTagView, self).get_queryset()
        return queryset.filter(tags__slug=self.kwargs['slug'])


class TagDetailView(DetailView):
    """Display all blog posts with a given tag."""
    model = Tag

    def get_context_data(self, **kwargs):
        context = super(TagDetailView, self).get_context_data(**kwargs)
        context['object_list'] = Post.objects.published().filter(tags__slug=self.kwargs['slug'])
        return context

Answer

Simeon Visser picture Simeon Visser · Mar 19, 2012

As a rule of thumb, look at the parameters in the URL. If you're using a slug of a Tag then you're most likely dealing with a DetailView and not a ListView.

In this case, the second approach uses less code and it is more elegant. However, it also depends on what you're going to do with the view later on. If you're going to add forms to edit the posts, it might make sense to use a ListView instead. But there's no technical reason to prefer one over the other, it's just that you might end up writing more code in one approach than in the other.