SyntaxStudy
Sign Up
Django Class-Based Views (CBV)
Django Beginner 1 min read

Class-Based Views (CBV)

Class-based views (CBVs) are an alternative way to write views using Python classes. Django ships with a comprehensive collection of generic CBVs that implement common patterns — listing objects, showing detail pages, creating/updating/deleting records, and more. By inheriting from these classes and setting a small number of attributes you can build fully functional views with very little code. CBVs are particularly powerful for CRUD operations. CreateView, UpdateView, and DeleteView handle form rendering, validation, saving, and redirecting. ListView provides pagination and queryset filtering. DetailView fetches a single object by primary key or slug. Each generic view has well-defined hooks (get_queryset, get_object, get_context_data, form_valid) that you override to customise behaviour rather than rewriting the entire view. The LoginRequiredMixin and PermissionRequiredMixin classes provide authentication and authorisation for CBVs. Mixins are Python classes that contribute specific behaviour through multiple inheritance. Django's CBV system uses mixins heavily, and you can write your own reusable mixins to share logic across multiple views without duplicating code.
Example
# blog/views.py — class-based views
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 Post
from .forms import PostForm


class PostListView(ListView):
    model               = Post
    template_name       = 'blog/post_list.html'
    context_object_name = 'posts'
    paginate_by         = 10

    def get_queryset(self):
        return Post.published.select_related('author').order_by('-published_at')


class PostDetailView(DetailView):
    model               = Post
    template_name       = 'blog/post_detail.html'
    context_object_name = 'post'

    def get_queryset(self):
        return Post.published.all()


class PostCreateView(LoginRequiredMixin, CreateView):
    model         = Post
    form_class    = PostForm
    template_name = 'blog/post_form.html'

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('post-detail', kwargs={'pk': self.object.pk})


class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model         = Post
    form_class    = PostForm
    template_name = 'blog/post_form.html'

    def test_func(self):
        return self.get_object().author == self.request.user

    def get_success_url(self):
        return reverse_lazy('post-detail', kwargs={'pk': self.object.pk})


class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model      = Post
    success_url = reverse_lazy('post-list')

    def test_func(self):
        return self.get_object().author == self.request.user