When building web applications using Django, views play a crucial role in defining the behavior and functionality of the app. While function-based views (FBVs) have been the traditional way of writing views in Django, class-based views (CBVs) have gained popularity due to their simplicity, reusability, and easy implementation of complex functionality.
In this article, we’ll learn the basics of CBVs in Django, their advantages over FBVs, and how to implement them in your Django project.
Advantages of Class-Based Views
CBVs offer several advantages over FBVs:
- Code Reusability: CBVs can be easily extended and modified, making them more reusable than FBVs. This is because CBVs are based on object-oriented principles, which makes it easier to inherit and extend from existing classes.
- Simplicity: CBVs provide a simplified way to write views in Django. With CBVs, you can write cleaner and more concise code, which is easier to read and maintain.
- Complex Functionality: CBVs make it easier to implement complex functionality such as pagination, form handling, and authentication. This is because CBVs provide a range of built-in methods and attributes that can be used to implement such functionality.
Anatomy of a Class-Based View
A CBV is a Python class that inherits from one of Django’s built-in generic views, such as TemplateView
, ListView
, CreateView
, UpdateView
, or DeleteView
. The following is the basic structure of a CBV:
from django.views.generic import View class MyView(View): # Define methods for handling HTTP requests def get(self, request, *args, **kwargs): # Handle GET request pass def post(self, request, *args, **kwargs): # Handle POST request pass
In the above example, MyView
is a CBV that inherits from Django’s View
class. The View
class is the most basic CBV and provides two methods for handling HTTP requests: get()
and post()
.
Commonly Used Class-Based Views
Django provides several built-in CBVs that can be used to implement common functionality in your web application:
TemplateView
The TemplateView
CBV is used to render a template. It’s a simple CBV that doesn’t require any model data to be passed to the template. The following is an example of how to use TemplateView
:
from django.views.generic import TemplateView class HomePageView(TemplateView): template_name = 'home.html'
In the above example, HomePageView
is a CBV that inherits from Django’s TemplateView
class. The template_name
attribute specifies the name of the template that will be rendered.
ListView
The ListView
CBV is used to display a list of objects from a model. It provides pagination and search functionality out of the box. The following is an example of how to use ListView
:
from django.views.generic import ListView from .models import Book class BookListView(ListView): model = Book paginate_by = 10
In the above example, BookListView
is a CBV that inherits from Django’s ListView
class. The model
attribute specifies the model from which the list of objects will be retrieved. The paginate_by
attribute specifies the number of objects to display per page.
CreateView
The CreateView
CBV is used to create a new object. It provides the implementation of the HTTP GET and POST methods to create a new object. The basic implementation of CreateView requires you to define the model, form_class, and template_name attributes.
Here’s an example of how to use CreateView:
from django.views.generic.edit import CreateView from myapp.models import MyModel from myapp.forms import MyModelForm class MyModelCreateView(CreateView): model = MyModel form_class = MyModelForm template_name = 'myapp/mymodel_create.html'
In the example above, MyModelCreateView
inherits from CreateView
and defines the model
, form_class
, and template_name
attributes. The model
attribute specifies the model to be used for creating the new object, while the form_class
attribute specifies the form to be used for creating the new object. The template_name
attribute specifies the template to be used for rendering the form.
UpdateView
The UpdateView CBV is used to update an existing object. It provides the implementation of the HTTP GET and POST methods to update an object. The basic implementation of UpdateView requires you to define the model, form_class, and template_name attributes, as well as the pk_url_kwarg attribute, which specifies the name of the URL keyword argument used to retrieve the object to be updated.
Here’s an example of how to use UpdateView:
from django.views.generic.edit import UpdateView from myapp.models import MyModel from myapp.forms import MyModelForm class MyModelUpdateView(UpdateView): model = MyModel form_class = MyModelForm template_name = 'myapp/mymodel_update.html' pk_url_kwarg = 'my_model_id'
In the example above, MyModelUpdateView
inherits from UpdateView
and defines the model
, form_class
, template_name
, and pk_url_kwarg
attributes. The model
attribute specifies the model to be used for updating the existing object, while the form_class
attribute specifies the form to be used for updating the existing object. The template_name
attribute specifies the template to be used for rendering the form. The pk_url_kwarg
attribute specifies the name of the URL keyword argument used to retrieve the object to be updated.
DeleteView
The DeleteView CBV is used to delete an existing object. It provides the implementation of the HTTP GET and POST methods to delete an object. The basic implementation of DeleteView requires you to define the model, success_url, and template_name attributes, as well as the pk_url_kwarg attribute, which specifies the name of the URL keyword argument used to retrieve the object to be deleted.
Here’s an example of how to use DeleteView:
from django.views.generic.edit import DeleteView from myapp.models import MyModel class MyModelDeleteView(DeleteView): model = MyModel success_url = '/myapp/mymodel_list/' template_name = 'myapp/mymodel_confirm_delete.html' pk_url_kwarg = 'my_model_id'
In the example above, MyModelDeleteView
inherits from DeleteView
and defines the model
, success_url
, template_name
, and pk_url_kwarg
attributes. The model
attribute specifies the model to be used for deleting the existing object, while the success_url
attribute specifies the URL to redirect to after the object has been deleted. The template_name
attribute specifies the template to be used for rendering the confirmation page. The pk_url_kwarg
attribute specifies the name of the primary key parameter that is passed in the URL. By default, it is ‘pk’, but it can be changed using this attribute.
UpdateView
The UpdateView CBV is used to update an existing object in the database. It is similar to the CreateView CBV but is used for updating objects rather than creating new ones.
Here is an example implementation of the UpdateView:
from django.views.generic.edit import UpdateView from .models import Book class BookUpdateView(UpdateView): model = Book fields = ['title', 'author', 'genre'] template_name = 'book_update.html' success_url = '/' pk_url_kwarg = 'book_id'
In this example, we are updating a Book
object. We specify the model and fields we want to update, the template name to render, and the URL to redirect to upon successful update. The pk_url_kwarg
attribute is also used to specify the name of the primary key parameter in the URL.
DeleteView
The DeleteView CBV is used to delete an existing object from the database. It is used to provide a confirmation page before deleting the object.
Here is an example implementation of the DeleteView:
from django.views.generic.edit import DeleteView from .models import Book class BookDeleteView(DeleteView): model = Book template_name = 'book_confirm_delete.html' success_url = '/' pk_url_kwarg = 'book_id'
In this example, we are deleting a Book
object. We specify the model, template name, and URL to redirect to upon successful deletion. The pk_url_kwarg
attribute is also used to specify the name of the primary key parameter in the URL.
Complex example of a CBV (uses multiple mixins and methods) –
from django.views.generic import ListView, CreateView, UpdateView, DeleteView from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from .models import Post class PostListView(ListView): model = Post template_name = 'blog/home.html' context_object_name = 'posts' ordering = ['-date_posted'] paginate_by = 5 class PostCreateView(LoginRequiredMixin, CreateView): model = Post fields = ['title', 'content'] template_name = 'blog/post_form.html' def form_valid(self, form): form.instance.author = self.request.user return super().form_valid(form) class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Post fields = ['title', 'content'] template_name = 'blog/post_form.html' def form_valid(self, form): form.instance.author = self.request.user return super().form_valid(form) def test_func(self): post = self.get_object() if self.request.user == post.author: return True return False class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): model = Post success_url = '/' template_name = 'blog/post_confirm_delete.html' def test_func(self): post = self.get_object() if self.request.user == post.author: return True return False
In this example, we have four CBVs: PostListView
, PostCreateView
, PostUpdateView
, and PostDeleteView
.
PostListView
is a basic ListView
that displays a list of all Post
objects in reverse chronological order. It uses pagination to display five posts per page.
PostCreateView
is a CreateView
that allows authenticated users to create new Post
objects. It displays a form with two fields: title
and content
. When the form is submitted, the form_valid
method is called, which sets the author
field to the current user and saves the object.
PostUpdateView
is an UpdateView
that allows authenticated users to update their own Post
objects. It uses the UserPassesTestMixin
to ensure that only the author of a post can edit it. The test_func
method checks if the current user is the author of the post being edited. If not, the user is redirected to a 403 error page.
PostDeleteView
is a DeleteView
that allows authenticated users to delete their own Post
objects. It uses the UserPassesTestMixin
to ensure that only the author of a post can delete it. The test_func
method works the same as in PostUpdateView
.
Overall, CBVs provide a powerful and flexible way to handle common CRUD operations in Django. With mixins and the ability to override individual methods, you can easily customize the behavior of your views to suit your specific needs.
Use of multiple class-based views in Django:
# urls.py from django.urls import path from .views import ( BlogListView, BlogDetailView, BlogCreateView, BlogUpdateView, BlogDeleteView, ) app_name = 'blog' urlpatterns = [ path('', BlogListView.as_view(), name='blog_list'), path('<int:pk>/', BlogDetailView.as_view(), name='blog_detail'), path('create/', BlogCreateView.as_view(), name='blog_create'), path('<int:pk>/update/', BlogUpdateView.as_view(), name='blog_update'), path('<int:pk>/delete/', BlogDeleteView.as_view(), name='blog_delete'), ]
# views.py from django.views.generic import ListView, DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.urls import reverse_lazy from .models import BlogPost class BlogListView(ListView): model = BlogPost template_name = 'blog/blog_list.html' context_object_name = 'posts' ordering = ['-created_on'] class BlogDetailView(DetailView): model = BlogPost template_name = 'blog/blog_detail.html' context_object_name = 'post' class BlogCreateView(CreateView): model = BlogPost template_name = 'blog/blog_create.html' fields = ('title', 'content',) success_url = reverse_lazy('blog:blog_list') class BlogUpdateView(UpdateView): model = BlogPost template_name = 'blog/blog_update.html' fields = ('title', 'content',) success_url = reverse_lazy('blog:blog_list') class BlogDeleteView(DeleteView): model = BlogPost template_name = 'blog/blog_delete.html' success_url = reverse_lazy('blog:blog_list')
This code defines five different views for a blog application. The BlogListView
and BlogDetailView
classes are used for listing and viewing individual blog posts, respectively. The BlogCreateView
, BlogUpdateView
, and BlogDeleteView
classes handle creating, updating, and deleting blog posts. Each view inherits from the appropriate Django class-based view and specifies various attributes such as the template name, model, and success URL.
By using class-based views, this code provides a clean, modular way to handle the various actions a user might take within the blog application. The code is also highly reusable, as it can be easily adapted for use in other applications with minimal modification.
Last Updated on April 29, 2023 by admin