Introduction
Class-Based Views (CBVs) in Django provide an object-oriented approach to handling HTTP requests. They offer better code reuse through inheritance and mixins.
Basic Class-Based Views
from django.views import View
from django.shortcuts import render, redirect
from django.http import JsonResponse
from .models import Article
from .forms import ArticleForm
class ArticleListView(View):
def get(self, request):
articles = Article.objects.all()
return render(request, 'articles/list.html', {'articles': articles})
def post(self, request):
form = ArticleForm(request.POST)
if form.is_valid():
form.save()
return redirect('article_list')
return render(request, 'articles/form.html', {'form': form})
class ArticleDetailView(View):
def get(self, request, pk):
try:
article = Article.objects.get(pk=pk)
return render(request, 'articles/detail.html', {'article': article})
except Article.DoesNotExist:
return JsonResponse({'error': 'Not found'}, status=404)
Generic Views
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Article
from .forms import ArticleForm
class ArticleListView(ListView):
model = Article
template_name = 'articles/list.html'
context_object_name = 'articles'
paginate_by = 10
queryset = Article.objects.filter(status='published')
class ArticleDetailView(DetailView):
model = Article
template_name = 'articles/detail.html'
context_object_name = 'article'
class ArticleCreateView(CreateView):
model = Article
form_class = ArticleForm
template_name = 'articles/form.html'
success_url = reverse_lazy('article_list')
class ArticleUpdateView(UpdateView):
model = Article
form_class = ArticleForm
template_name = 'articles/form.html'
success_url = reverse_lazy('article_list')
class ArticleDeleteView(DeleteView):
model = Article
template_name = 'articles/confirm_delete.html'
success_url = reverse_lazy('article_list')
Mixins
from django.views.generic import ListView
from django.core.paginator import Paginator
from django.http import JsonResponse
class PaginationMixin:
paginate_by = 10
def get_paginate_by(self, queryset):
return self.request.GET.get('page_size', self.paginate_by)
class JSONResponseMixin:
def render_to_json_response(self, context, **response_kwargs):
return JsonResponse(self.get_context_data(**response_kwargs))
class ArticleListView(PaginationMixin, ListView):
model = Article
def get_queryset(self):
return Article.objects.filter(author=self.request.user)
class MultipleObjectMixin:
def get_queryset(self):
return super().get_queryset().filter(is_active=True)
URLs Configuration
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.ArticleListView.as_view(), name='article_list'),
path('articles/<int:pk>/', views.ArticleDetailView.as_view(), name='article_detail'),
path('articles/create/', views.ArticleCreateView.as_view(), name='article_create'),
path('articles/<int:pk>/edit/', views.ArticleUpdateView.as_view(), name='article_update'),
path('articles/<int:pk>/delete/', views.ArticleDeleteView.as_view(), name='article_delete'),
]
Practice Problems
- Create a View that returns JSON for API requests and HTML for regular requests
- Implement a paginated list view that allows sorting by different fields
- Build a CreateView with a custom form that pre-fills data from the request
- Create a mixin that adds caching functionality to any view
- Implement a view that handles both GET and POST with different logic