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')
