An Introduction to Class‑Based Views in Django: Structure, Usage, and Advanced Features

This article explains how class‑based views (CBVs) work in Django, how they differ from function‑based views, how to use them in URL configurations, how to subclass and extend them, how to support additional HTTP methods such as HEAD, and how to build asynchronous class‑based views. It provides a clear overview of Django’s CBV architecture and practical examples for real‑world applications.

Django class-based views, CBVTemplateViewListView, async views

~3 min read · Updated Mar 14, 2026

Introduction

In Django, a view is any callable that receives an HTTP request and returns a response. While views are often written as simple functions, Django also provides a powerful system of class‑based views (CBVs). These allow developers to structure views using object‑oriented principles such as inheritance and mixins, making code more reusable and maintainable.


What Are Class‑Based Views?

Class‑based views are Python classes that implement view logic through methods. All CBVs inherit from Django’s base View class, which handles URL integration, HTTP method dispatching, and other shared functionality. Django also includes several generic CBVs for common tasks, such as rendering templates or listing objects.


Basic Examples of Built‑In CBVs

Django provides several foundational CBVs:

  • View: the base class for all CBVs.
  • RedirectView: returns an HTTP redirect.
  • TemplateView: renders a template.

Using CBVs in URLconf

The simplest way to use a class‑based view is to call its as_view() method directly in your URL configuration:


from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path("about/", TemplateView.as_view(template_name="about.html")),
]

Arguments passed to as_view() override class attributes, making it easy to customize behavior without subclassing.


Subclassing Generic Views

A more powerful approach is to subclass an existing CBV and override attributes or methods. For example, to create a dedicated view for an about.html page:


# some_app/views.py
from django.views.generic import TemplateView

class AboutView(TemplateView):
    template_name = "about.html"

Then add it to your URLconf:


# urls.py
from django.urls import path
from some_app.views import AboutView

urlpatterns = [
    path("about/", AboutView.as_view()),
]

Supporting Additional HTTP Methods

CBVs make it easy to support multiple HTTP methods by defining methods such as get(), post(), put(), or head(). Here’s an example using HEAD to optimize API responses for a book list:


from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
    model = Book

    def head(self, *args, **kwargs):
        last_book = self.get_queryset().latest("publication_date")
        response = HttpResponse(
            headers={
                "Last-Modified": last_book.publication_date.strftime(
                    "%a, %d %b %Y %H:%M:%S GMT"
                )
            }
        )
        return response

A GET request returns the full list of books, while a HEAD request returns only headers, allowing clients to check whether new data exists without downloading the entire response.


Asynchronous Class‑Based Views

Django supports asynchronous CBVs using async def method handlers. This is useful for I/O‑bound operations such as external API calls.


import asyncio
from django.http import HttpResponse
from django.views import View

class AsyncView(View):
    async def get(self, request, *args, **kwargs):
        await asyncio.sleep(1)
        return HttpResponse("Hello async world!")

Important: all user‑defined handlers in a single CBV must be either synchronous or asynchronous. Mixing def and async def will raise an ImproperlyConfigured error.


Conclusion

Class‑based views provide a structured, reusable, and powerful way to build views in Django. Whether you’re rendering templates, handling forms, building APIs, or leveraging asynchronous operations, CBVs offer a flexible foundation for organizing your application’s logic. By understanding how to subclass, override methods, and support additional HTTP methods, you can create clean and maintainable view architectures.

Written & researched by Dr. Shahin Siami

Related Articles

Django Tasks Framework: A Complete Guide to Background Task Execution in Django 6.0

Django 6.0 introduces the Tasks framework, a built‑in system for defining and queuing background work outside the request–response cycle. This article explains how Tasks work, how to configure backends, how to define and enqueue tasks, how context works, and how to integrate third‑party worker systems for production environments.

Continue

Asynchronous Support in Django: A Complete Guide to Async Views, ORM, Middleware, Performance, and Safety

This article explains Django’s asynchronous (async) capabilities, including async views, ASGI support, middleware behavior, async ORM features, performance considerations, handling disconnects, and Django’s async safety protections. It also covers how to use sync_to_async(), async ORM methods, and how to safely run synchronous code in async environments.

Continue

Django System Check Framework: A Complete Guide to Writing, Registering, Running, and Testing System Checks

This article explains Django’s System Check Framework—a powerful mechanism for detecting configuration issues, validating project structure, and ensuring code quality. It covers how checks are executed, how to write custom checks, how messages work, how to register and tag checks, how to extend checks for fields and models, and how to write both unit and integration tests for system checks.

Continue

Django Signals: A Complete Guide to Listening, Connecting, Sending, and Managing Application Events

This article provides a comprehensive explanation of Django’s signal system—an event‑driven mechanism that allows decoupled applications to react to actions occurring elsewhere in the framework. It covers how to define receivers, connect signals, use decorators, handle specific senders, organize signal code, and follow best practices to avoid complexity.

Continue

Understanding Django Settings: Configuration, Environment Management, and Best Practices

This article provides a complete overview of Django’s settings system. It explains how settings files work, how to designate a settings module, how to use settings in your code, how to configure Django manually, how to secure sensitive settings, and how to work with custom default settings. It also covers the role of django.setup() for standalone scripts.

Continue

Serializing and Deserializing Django Objects: A Complete Guide to Django’s Serialization Framework

This article explains Django’s serialization framework, including how to serialize and deserialize model instances, work with subsets of fields, handle inherited models, use different serialization formats (JSON, XML, YAML, JSONL), and understand how relational fields are represented. It also covers DeserializedObject behavior and common pitfalls.

Continue