Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Models, Views, Admin and Tests  ›  Lesson

Class-Based Views

Class-based views 16 minA class-based view organises a view as a class with one method per HTTP verb, and generic class-based views such as ListView and DetailView supply the common patterns so you only set what differs.

Class-Based Views

After a few weeks, the cookbook's views.py shows a pattern: list some objects, show one object, handle a form. Every list view looks the same apart from the model. Class-based views let Django own that repeated shape, so your code states only what is different.

The rule

A class per view, a method per verb; generic views fill in the rest.

The base View class sends each request to the method named after its HTTP verb:

from django.shortcuts import render
from django.views import View

class RecipeSearchView(View):
    def get(self, request):
        return render(request, "recipes/search.html")

    def post(self, request):
        ...   # handle the submitted search

If a verb has no method, say a DELETE, Django answers 405 Method Not Allowed for you. No if request.method == ... branches.

URL patterns need a function, so every class-based view is wired in with .as_view():

path("search/", views.RecipeSearchView.as_view(), name="search"),

The real payoff is generic views, ready-made classes for common jobs:

from django.views.generic import DetailView, ListView
from .models import Recipe

class RecipeListView(ListView):
    model = Recipe
    ordering = ["-created"]

class RecipeDetailView(DetailView):
    model = Recipe
path("", views.RecipeListView.as_view(), name="list"),
path("<slug:slug>/", views.RecipeDetailView.as_view(), name="detail"),

Those few lines replace both function views. From model = Recipe, Django works out the rest by convention:

  • ListView renders recipes/recipe_list.html with object_list (and recipe_list) in the context.
  • DetailView reads slug (or pk) from the URL, finds that recipe, raises 404 if none exists, and renders recipes/recipe_detail.html with object (and recipe).

To change behaviour, override an attribute or method: template_name, paginate_by = 10, or get_queryset() to filter.

Function views are not obsolete. A one-off page with unusual logic is often clearer as a function. Use classes when the job matches a pattern Django already knows.

The shortcut

Ask "which generic view already does this?" List of things → ListView. One thing → DetailView. Create, edit, delete → CreateView, UpdateView, DeleteView. Then set attributes until it fits.

Showing only quick recipes as a classStep 1 of 4
  1. Pick the generic

    It is a list, so ListView.

The classic slip is writing views.RecipeListView in urls.py without .as_view(); the class itself is not a view function, and the page breaks.

Drills

Answer fast — trust the rule.

quick drill

How do you use RecipeListView in a URL pattern?

quick drill

A View subclass defines only get(). What does a POST request receive?

quick drill

Which template does DetailView with model = Recipe look for by default?

quick drill

A ListView should show only recipes under 30 minutes. What do you override?

Remember

  • A class per view, a method per verb; generic views fill in the rest.
  • Ask "which generic view already does this?", then override only what differs.
  • Trap: forgetting .as_view() in urls.py.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainSwap functions for classes

Rewrite the cookbook's recipe list and recipe detail views as generic class-based views, show the URL patterns that use them, and explain what Django now does for you that the function versions did by hand.