What Is a Class-Based View?
A class-based view (CBV) organizes request handling as methods on a Python class instead of a single function: get() handles GET requests, post() handles POST requests, and so on, dispatched automatically by the View base class's as_view() and dispatch() machinery. When Django resolves a URL to a CBV, as_view() returns a function that instantiates the class per request and calls dispatch(), which looks at request.method and routes to the matching method by name. This means the method-branching that FBVs do manually with if/elif is handled for you automatically by the framework.
Cricket analogy: It's like a specialist all-rounder such as Ravindra Jadeja who bats, bowls, and fields, with the team management (dispatch) automatically deciding which skill (method) to call on depending on the match situation (HTTP method).
Generic Class-Based Views
Django ships a library of generic CBVs — ListView, DetailView, CreateView, UpdateView, DeleteView, and TemplateView — that implement common CRUD patterns with minimal code. For example, ListView only requires you to set model and template_name (or override get_queryset) and it automatically handles pagination via paginate_by, context population, and template rendering. This dramatically reduces boilerplate for standard listing and detail pages compared to writing the equivalent FBV by hand, though it requires learning each generic view's attribute names and method resolution order (MRO).
Cricket analogy: It's like using a pre-set fielding template for a T20 powerplay instead of placing each fielder individually every match; you just tweak a couple of positions (attributes) and the standard setup (ListView) handles the rest.
from django.views.generic import ListView, DetailView, CreateView
from django.urls import reverse_lazy
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'articles/list.html'
context_object_name = 'articles'
paginate_by = 20
def get_queryset(self):
return Article.objects.filter(published=True).order_by('-created_at')
class ArticleCreateView(CreateView):
model = Article
fields = ['title', 'body', 'published']
template_name = 'articles/form.html'
success_url = reverse_lazy('article_list')Mixins for Reusable Behavior
CBVs support multiple inheritance, so Django provides mixins like LoginRequiredMixin, PermissionRequiredMixin, and UserPassesTestMixin that you stack alongside a generic view class to layer in cross-cutting behavior without rewriting logic. Because Python resolves methods via the MRO (Method Resolution Order), mixin order in the class definition matters: access-control mixins are conventionally listed first (leftmost) so their dispatch() or test logic runs before the generic view's own dispatch(). This composability is the main advantage CBVs have over FBVs for larger applications with many similar views.
Cricket analogy: It's like adding a fielding-restriction rule (mixin) on top of the base T20 rules (base class) — the powerplay restriction layers onto the standard game without rewriting the whole rulebook.
Use as_view() when mapping a CBV in urls.py — e.g., path('articles/', ArticleListView.as_view(), name='article_list') — because as_view() returns the actual callable Django's URL resolver needs; you never map the class itself.
Mixin order is not cosmetic: placing LoginRequiredMixin after a generic view class in the MRO can cause the permission check to run too late or not at all, silently exposing a view you intended to protect.
- CBVs dispatch HTTP methods to same-named methods (get(), post(), etc.) automatically via View.dispatch().
- Generic CBVs like ListView, DetailView, CreateView, UpdateView, and DeleteView implement common CRUD flows with minimal configuration.
- Mixins (LoginRequiredMixin, PermissionRequiredMixin) add reusable cross-cutting behavior via multiple inheritance.
- Mixin ordering matters because Python resolves methods left-to-right through the MRO — access-control mixins go first.
- Always map CBVs in urls.py using ClassName.as_view(), never the raw class.
- CBVs trade some readability/transparency for significant boilerplate reduction on repetitive CRUD views.
- Overriding get_queryset(), get_context_data(), or form_valid() is the standard way to customize generic CBV behavior.
Practice what you learned
1. What must you call when mapping a class-based view in urls.py?
2. Which generic CBV is best suited for displaying a paginated list of objects?
3. Why does mixin order matter in a class-based view's inheritance list?
4. Which method would you override in a CreateView to add extra context data to the template?
Was this page helpful?
You May Also Like
Function-Based Views
Learn how Django's function-based views (FBVs) take a request and return a response using plain Python functions, and when they're the right choice over class-based views.
URL Routing in Django
Learn how Django maps incoming request paths to views using urlpatterns, path converters, included URLconfs, and named URLs for reversible linking.
Context and Template Tags
Understand how Django builds the template context (including automatic context processors) and how to write custom template tags and filters for reusable presentation logic.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentNext.js Study Notes
JavaScript · 30 topics