Django Class-Based Views

So far we have written all our views as functions — this is called Function-Based Views (FBV). Django also provides a more advanced and reusable approach called Class-Based Views (CBV). These use Python classes to handle web requests, and Django provides many powerful built-in CBV templates that save you from writing repetitive code.

What are Class-Based Views?

A Class-Based View is a Python class (instead of a function) that handles HTTP requests. The same view class can handle different request types (GET, POST) inside separate methods — making the code more organized and easier to reuse.

Example: Imagine a customer service desk (view). With a function-based approach, one person handles everything — new inquiries, complaints, and returns — all in one go, and you have to write separate instructions for each action. With a class-based approach, the desk has specialized staff: one for new inquiries (GET), one for processing returns (POST). Each person knows exactly what to do — the desk is more organized and reusable.

Function-Based vs Class-Based — Side by Side

Here is the same "student list" view written both ways:

Function-Based View


from django.shortcuts import render
from .models import Student

def student_list(request):
    students = Student.objects.all()
    return render(request, 'student_list.html', {'students': students})

Class-Based View (using ListView)


from django.views.generic import ListView
from .models import Student

class StudentListView(ListView):
    model = Student
    template_name = 'student_list.html'
    context_object_name = 'students'

Both do exactly the same thing. But the class-based version is shorter and Django handles all the logic (fetching records, passing to template) automatically.

Connecting a Class-Based View to a URL

Class-Based Views need to be converted to callable functions using .as_view() when connecting to a URL:


# school/urls.py

from django.urls import path
from .views import StudentListView

urlpatterns = [
    path('students/', StudentListView.as_view(), name='student-list'),
]

Django's Built-in Generic Class-Based Views

Django provides ready-made CBVs for the most common web operations. You just set a few attributes and the view is done. These are called Generic Views:

TemplateView — Display a Simple Page

Use this when you just need to render an HTML page without any database query:


from django.views.generic import TemplateView

class AboutView(TemplateView):
    template_name = 'about.html'
Example: TemplateView is like an information kiosk that simply displays a fixed poster (template). No database needed — just show the page.

ListView — Display a List of Records

Use this to show a list of model records (like all students, all products):


from django.views.generic import ListView
from .models import Student

class StudentListView(ListView):
    model = Student
    template_name = 'student_list.html'
    context_object_name = 'students'   # Name used in the template
    ordering = ['name']                # Sort alphabetically
    paginate_by = 10                   # Show 10 records per page

DetailView — Display a Single Record

Use this to show the full details of one specific record (like one student's profile page):


from django.views.generic import DetailView
from .models import Student

class StudentDetailView(DetailView):
    model = Student
    template_name = 'student_detail.html'
    context_object_name = 'student'

URL for DetailView needs a primary key or slug:


path('student/<int:pk>/', StudentDetailView.as_view(), name='student-detail'),

Visiting /student/3/ automatically fetches the Student with id=3 and passes it to the template. Django handles this lookup automatically — no extra code needed.

CreateView — Add a New Record

Use this to show a form and save a new record to the database:


from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Student

class StudentCreateView(CreateView):
    model = Student
    fields = ['name', 'age', 'grade', 'email']
    template_name = 'student_form.html'
    success_url = reverse_lazy('student-list')  # Redirect here after saving
Example: CreateView is like an automated admission form processor. You give it the model and the fields to show — it draws the form, validates it, saves the record, and redirects to the list page. All without you writing a single line of form handling code.

UpdateView — Edit an Existing Record


from django.views.generic.edit import UpdateView
from django.urls import reverse_lazy
from .models import Student

class StudentUpdateView(UpdateView):
    model = Student
    fields = ['name', 'age', 'grade', 'email']
    template_name = 'student_form.html'
    success_url = reverse_lazy('student-list')

URL:


path('student/<int:pk>/edit/', StudentUpdateView.as_view(), name='student-update'),

DeleteView — Delete a Record


from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
from .models import Student

class StudentDeleteView(DeleteView):
    model = Student
    template_name = 'student_confirm_delete.html'
    success_url = reverse_lazy('student-list')

URL:


path('student/<int:pk>/delete/', StudentDeleteView.as_view(), name='student-delete'),

Django automatically shows a confirmation page before deleting. The template needs a confirmation form:


<h3>Are you sure you want to delete {{ student.name }}?</h3>
<form method="post">
    {% csrf_token %}
    <button type="submit">Yes, Delete</button>
    <a href="{% url 'student-list' %}">Cancel</a>
</form>

Full CRUD URL Setup with Class-Based Views


# school/urls.py

from django.urls import path
from .views import (StudentListView, StudentDetailView,
                    StudentCreateView, StudentUpdateView, StudentDeleteView)

urlpatterns = [
    path('students/', StudentListView.as_view(), name='student-list'),
    path('student/<int:pk>/', StudentDetailView.as_view(), name='student-detail'),
    path('student/add/', StudentCreateView.as_view(), name='student-create'),
    path('student/<int:pk>/edit/', StudentUpdateView.as_view(), name='student-update'),
    path('student/<int:pk>/delete/', StudentDeleteView.as_view(), name='student-delete'),
]

Adding Login Protection to Class-Based Views

To protect a CBV so only logged-in users can access it, use LoginRequiredMixin. Always add it as the first class in the inheritance list:


from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from .models import Student

class StudentListView(LoginRequiredMixin, ListView):
    model = Student
    template_name = 'student_list.html'
    context_object_name = 'students'
Example: LoginRequiredMixin is like putting a lock on a room door before attaching the room to a building. Any class-based view that inherits this mixin automatically requires a login badge before entry.

Quick Recap — Generic CBV Cheat Sheet


TemplateView  → Shows a static page
ListView      → Shows a list of model records
DetailView    → Shows one record's details (needs <int:pk> in URL)
CreateView    → Shows a form to create a new record
UpdateView    → Shows a form to edit an existing record (needs <int:pk> in URL)
DeleteView    → Shows a confirm page before deleting (needs <int:pk> in URL)

# Always connect with .as_view() in urls.py
path('students/', StudentListView.as_view(), name='student-list'),

# Always use reverse_lazy() (not reverse()) in success_url
success_url = reverse_lazy('student-list')

Leave a Comment

Your email address will not be published. Required fields are marked *