Class-Based Views vs Function-Based Views
Django offers two ways to write views: functions and classes. Function-based views are simple and straightforward. Class-based views offer more structure and reuse through inheritance.
CBVs might seem more complex at first, but they shine when you need to share logic between views. Mixins let you plug in behaviors like authentication checks or extra context data without copying code around.
The View Base Class
Every class-based view inherits from Django's View class. You define methods for each HTTP method you want to handle — get(), post(), put(), delete(), and so on.
from django.views import View
from django.http import HttpResponse
class HelloView(View):
def get(self, request):
return HttpResponse('Hello from a class-based view!')
def post(self, request):
return HttpResponse('POST received!')
The as_view() class method converts your class into a callable that Django's URL system can use. You don't call it directly — Django calls it for you.
Using as_view() in URLs
When mapping a class-based view to a URL, use as_view(). This creates a view function that Django can call when a request comes in.
from django.urls import path
from .views import HelloView
urlpatterns = [
path('hello/', HelloView.as_view(), name='hello'),
path('hello/<int:pk>/', HelloView.as_view(), name='hello_detail'),
]
You can pass keyword arguments to as_view() to set attributes on the view instance. This is useful for overriding template names or other settings without subclassing.
Useful Mixins
Mixins add reusable functionality to your views. They're the secret weapon of class-based views. You combine multiple mixins to build views with exactly the behavior you need.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
class DashboardView(LoginRequiredMixin, TemplateView):
template_name = 'dashboard.html'
login_url = '/login/'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['username'] = self.request.user.username
return context
LoginRequiredMixin requires users to be logged in. ContextMixin lets you add extra context data. TemplateResponseMixin adds template rendering. Order matters — mixins listed first have higher priority.
The dispatch() Method
The dispatch() method is the entry point for every request. It examines the HTTP method and routes to the appropriate handler method. You can override it to add pre-processing logic.
from django.views import View
from django.http import HttpResponse
class CustomView(View):
def dispatch(self, request, *args, **kwargs):
if request.method == 'GET':
return self.handle_get(request)
return super().dispatch(request, *args, **kwargs)
def handle_get(self, request):
return HttpResponse('Custom GET handling')
In most cases, you won't need to override dispatch(). Define get(), post(), and other method handlers instead.