Class-Based Views (CBV)0%

Class-Based Views (CBV)

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Class-Based Views (CBV)

While Function-Based Views are simple and explicit, standard web applications contain repetitive CRUD operations: listing records, displaying details, creating records via forms, updating instances, and deleting rows. Django's Class-Based Views (CBVs) and Generic Class-Based Views (GCBVs) use object-oriented patterns, mixins, and inheritance to eliminate hundreds of lines of boilerplate.


1. The Class-Based View Hierarchy

Output
View (Base Class)
└── TemplateView (Renders static template)
└── RedirectView (Handles HTTP redirects)
└── DetailView (Fetches single object by pk/slug)
└── ListView (Fetches paginated list of objects)
└── FormView (Validates arbitrary form)
└── CreateView (Validates ModelForm and saves new instance)
└── UpdateView (Validates ModelForm and updates existing instance)
└── DeleteView (Handles confirmation and deletes instance)

2. Implementing Standard CRUD with Generic Views

Python
# articles/views.py
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse_lazy
from .models import Article
 
# 1. LIST: Paginated Article Directory
class ArticleListView(ListView):
model = Article
template_name = "articles/article_list.html"
context_object_name = "articles"
paginate_by = 10
 
def get_queryset(self):
# Override query to return only published articles
return Article.objects.filter(status="published").select_related("author")
 
# 2. DETAIL: Single Article View
class ArticleDetailView(DetailView):
model = Article
template_name = "articles/article_detail.html"
context_object_name = "article"
slug_field = "slug"
slug_url_kwarg = "slug"
 
# 3. CREATE: Form Generation & Persistence
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
fields = ["title", "content", "category", "tags", "status"]
template_name = "articles/article_form.html"
 
def form_valid(self, form):
# Automatically inject authenticated user as author
form.instance.author = self.request.user
return super().form_valid(form)
 
# 4. UPDATE: Guarded by Author Ownership
class ArticleUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Article
fields = ["title", "content", "category", "status"]
template_name = "articles/article_form.html"
 
# Authorization guard: only author can edit!
def test_func(self):
article = self.get_object()
return self.request.user == article.author
 
# 5. DELETE: Confirmation & Teardown
class ArticleDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Article
template_name = "articles/article_confirm_delete.html"
success_url = reverse_lazy("articles:list")
 
def test_func(self):
article = self.get_object()
return self.request.user == article.author

3. Connecting CBVs in urls.py with as_view()

URL dispatchers expect a callable function. CBVs provide the .as_view() class method to generate the callable:

Python
# articles/urls.py
from django.urls import path
from .views import (
ArticleListView,
ArticleDetailView,
ArticleCreateView,
ArticleUpdateView,
ArticleDeleteView,
)
 
app_name = "articles"
 
urlpatterns = [
path("", ArticleListView.as_view(), name="list"),
path("create/", ArticleCreateView.as_view(), name="create"),
path("<slug:slug>/", ArticleDetailView.as_view(), name="detail"),
path("<slug:slug>/edit/", ArticleUpdateView.as_view(), name="edit"),
path("<slug:slug>/delete/", ArticleDeleteView.as_view(), name="delete"),
]

4. Why reverse_lazy is Required in Class Attributes

In class definitions, class attributes (success_url = reverse_lazy('...')) are evaluated when the Python module is first imported. Standard reverse() fails because URL patterns haven't finished loading yet. reverse_lazy() defers evaluation until the URL is actually accessed!


Interactive Quiz

Practice Quiz

Question 1
What method must always be called when registering a Class-Based View in urls.py?
Question 2
What mixin is used in CBVs to require that a user be logged in, equivalent to the @login_required decorator?
Question 3
Why is reverse_lazy() used for success_url class attributes instead of standard reverse()?
Question 4
How does UserPassesTestMixin enforce custom authorization rules on a CBV?
Question 5
In a CreateView, how do you inject the current logged-in user as the model author before saving?
Next Lesson

URL Dispatcher and Routing

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext