Class-based views help in composing reusable bits of behavior. Django REST Framework provides several pre-built views that allow us to reuse common functionality and keep our code DRY. In this section, we will dig deep into the different class-based views in Django REST Framework.
This article assumes you are already familiar with Django and Django REST Framework.
Checkout -
APIView
APIView class provides commonly required behavior for standard list and detail views. With APIView class, we can rewrite the root view as a class-based view. They provide action methods such as get(), post(), put(), patch(), and delete() rather than defining the handler methods.
Creating views using APIView
Let's take a look at how to create views using APIView. The views.py file module as follows:
Python3
from django.shortcuts import render
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(APIView):
"""
List all Transformers, or create a new Transformer
"""
def get(self, request, format=None):
transformers = Transformer.objects.all()
serializer = TransformerSerializer(transformers, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = TransformerSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,
status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TransformerDetail(APIView):
"""
Retrieve, update or delete a transformer instance
"""
def get_object(self, pk):
# Returns an object instance that should
# be used for detail views.
try:
return Transformer.objects.get(pk=pk)
except Transformer.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer)
return Response(serializer.data)
def put(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, pk, format=None):
transformer = self.get_object(pk)
serializer = TransformerSerializer(transformer,
data=request.data,
partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
transformer = self.get_object(pk)
transformer.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
The code is similar to regular Django views, but there is a better separation between different HTTP Methods.
- The get() method process the HTTP GET request
- The post() method process the HTTP POST request
- The put() method process the HTTP PUT request
- The patch() method process the HTTP PATCH request
- The delete() method process the HTTP DELETE request
Setting URL Configuration
Since we are using class-based views the way we mention the views in the path of the urls.py file is slightly different. Create a new file named urls.py (if not exist) in the app (transformers) folder and add the below code
Python3
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from transformers import views
urlpatterns = [
path('transformers/', views.TransformerList.as_view()),
path('transformers/<int:pk>/', views.TransformerDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Next, set up the root URL configuration. You can open the urls.py (same folder where the settings.py file is located) and add the below code
Python3
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('transformers.urls')),
]
Composing and sending HTTP Requests
1. Create a new entry -
The HTTPie command is:
http POST :8000/transformers/ name="Optimus Prime" alternate_mode="1979 Freightliner Semi" description="Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader" alive="True"
Output
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:48:46 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
Sharing the command prompt screenshot for your reference:

2. Retrieve an existing entry
The pk value of Optimus Prime is 1. Let's pass the pk value and retrieve the details
The HTTPie command is:
http GET :8000/transformers/1/
Output
HTTP/1.1 200 OK
Allow: GET, HEAD, OPTIONS
Content-Length: 194
Content-Type: application/json
Date: Sat, 23 Jan 2021 03:50:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
Sharing the command prompt screenshot for your reference

3. Update an existing entry
Let's update the field named alive by setting it to False. The HTTPie command is:
http PUT :8000/transformers/1/ name="Optimus Prime" alternate_mode="1979 Freightliner Semi" description="Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader" alive="False"
Output
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 195
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:22:30 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous of all Autobots, he is also their leader",
"id": 1,
"name": "Optimus Prime"
}
Sharing the command prompt screenshot for your reference

4. Update partially an existing entry
Let's partially update the field named description. The HTTPie command is:
http PATCH :8000/transformers/1/ description="Optimus Prime is the strongest and most courageous and leader of all Autobots"
Output
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 181
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:32:40 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
"id": 1,
"name": "Optimus Prime"
}
Sharing the command prompt screenshot

5. Delete an existing entry
We will create a new entry and delete it. Let's create a 'Test' entry using the below HTTPie command:
http POST :8000/transformers/ name="Test"
Output
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 77
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:34:41 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": false,
"alternate_mode": null,
"description": null,
"id": 2,
"name": "Test"
}
Now let's delete the 'Test' entry (pk =2). The HTTPie command to delete entry is
http DELETE :8000/transformers/2/
Output
HTTP/1.1 204 No Content
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 0
Date: Sat, 23 Jan 2021 04:35:06 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Sharing the command prompt screenshot

Mixins
Mixin classes allow us to compose reusable bits of behavior. They can be imported from rest_framework.mixins. Let's discuss the different types of mixin classes
- ListModelMixin : It provides a .list(request, *args, **kwargs) method for listing a queryset. If the queryset is populated, the response body has a 200 OK response with a serialized representation of the queryset.
- CreateModelMixin: It provides a .create(request, *args, **kwargs) method for creating and saving a new model instance. If the object is created, the response body has a 201 Created response, with a serialized representation of the object. If invalid, it returns a 400 Bad Request response with the error details.
- RetrieveModelMixin: It provides a .retrieve(request, *args, **kwargs) method for returning an existing model instance in a response. If an object can be retrieved, the response body has a 200 OK response, with a serialized representation of the object. Otherwise, it will return a 404 Not Found.
- UpdateModelMixin: It provides a .update(request, *args, **kwargs) method for updating and saving an existing model instance. It also provides a .partial_update(request, *args, **kwargs) method for partially updating and an existing model instance. . If the object is updated, the response body has a 200 OK response, with a serialized representation of the object. Otherwise, 400 Bad Request response will be returned with the error details.
- DestroyModelMixin: It provides a .destroy(request, *args, **kwargs) method for deleting an existing model instance. If an object is deleted, the response body has a 204 No Content response, otherwise, it will return a 404 Not Found.
Note: We will be using GenericAPIView to build our views and adding in Mixins.
Creating Views using Mixins
Let's take a look at how we can make use of Mixin classes. The views.py file module as follows:
Python3
from rest_framework import mixins
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class TransformerDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
Here, the GenericAPIView class provides the core functionality, and we are adding mixin classes to it. The queryset and serializer_class are the basic attributes of GenericAPIView class. The queryset attribute is used for returning objects from this view and the serializer_class attribute is used for validating, deserializing input, and for serializing output.
In the TransformerList class, we make use of mixin classes that provide .list() and .create() actions and bind the actions to the get() and post() methods. In the TransformerDetail class we make use of mixin classes that provide .retrieve(), .update(), .partial_update(), and . destroy() actions and bind the actions to get(), put(), patch(), and delete() methods.
Composing and Sending HTTP Requests
1. Create a new entry
The HTTPie command is
http POST :8000/transformers/ name="Bumblebee" alternate_mode="1979 VW Beetle" description="Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy" alive="True"
Output
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 161
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:58:26 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
}
2. Retrieve all entries
The HTTPie command is
http GET :8000/transformers/
Output
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 345
Content-Type: application/json
Date: Sat, 23 Jan 2021 04:59:42 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
[
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave, Bumblebee acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
},
{
"alive": false,
"alternate_mode": "1979 Freightliner Semi",
"description": "Optimus Prime is the strongest and most courageous and leader of all Autobots",
"id": 1,
"name": "Optimus Prime"
}
]
Sharing the command prompt screenshot for your reference

Generic class-based views
To make use of generic class-based views, the view classes should import from rest_framework.generics.
- CreateAPIView: It provides a post method handler and it is used for create-only endpoints. CreateAPIView extends GenericAPIView and CreateModelMixin
- ListAPIView: It provides a get method handler and is used for read-only endpoints to represent a collection of model instances. ListAPIView extends GenericAPIView and ListModelMixin.
- RetrieveAPIView: It provides a get method handler and is used for read-only endpoints to represent a single model instance. RetrieveAPIView extends GenericAPIView and RetrieveModelMixin.
- DestroyAPIView: It provides a delete method handler and is used for delete-only endpoints for a single model instance. DestroyAPIView extends GenericAPIView and DestroyModelMixin.
- UpdateAPIView: It provides put and patch method handlers and is used for update-only endpoints for a single model instance. UpdateAPIView extends GenericAPIView and UpdateModelMixin.
- ListCreateAPIView: It provides get and post method handlers and is used for read-write endpoints to represent a collection of model instances. ListCreateAPIView extends GenericAPIView, ListModelMixin, and CreateModelMixin..
- RetrieveUpdateAPIView: It provides get, put, and patch method handlers. It is used to read or update endpoints to represent a single model instance. RetrieveUpdateAPIView extends GenericAPIView, RetrieveModelMixin, and UpdateModelMixin.
- RetrieveDestroyAPIView: It provides get and delete method handlers and it is used for read or delete endpoints to represent a single model instance. RetrieveDestroyAPIView extends GenericAPIView, RetrieveModelMixin, and DestroyModelMixin.
- RetrieveUpdateDestroyAPIView: It provides get, put, patch, and delete method handlers. It is used for read-write-delete endpoints to represent a single model instance. It extends GenericAPIView, RetrieveModelMixin, UpdateModelMixin, and DestroyModelMixin.
Creating views using generic class-based views
Let's take a look at how we can make use of Mixin classes. Here we will take advantage of ListCreateAPIView and RetrieveUpdateDestroyAPIView. The views.py file module as follows:
Python3
from rest_framework import generics
from transformers.models import Transformer
from transformers.serializers import TransformerSerializer
class TransformerList(generics.ListCreateAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Transformer.objects.all()
serializer_class = TransformerSerializer
You can notice that we were able to avoid a huge amount of boilerplate code. These generic views combine reusable bits of behavior from mixin classes. Let's look at the declaration of ListCreateAPIView and RetrieveUpdateDestroyAPIView:
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
......
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
GenericAPIView):
......
Composing and sending HTTP Requests
1. Create a new entry
The HTTPie command is
http POST :8000/transformers/ name="Cliffjumper" alternate_mode="1979 Porsche 924" description="His eagerness and daring have no equal" alive="True"
Output
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 133
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:28:45 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Porsche 924",
"description": "His eagerness and daring have no equal",
"id": 5,
"name": "Cliffjumper"
}
Sharing the command prompt screenshot for your reference

2. Update an existing entry
The HTTPie command is
http PUT :8000/transformers/5/ name="Cliffjumper" alternate_mode="1979 Porsche 924" description="Eager and Daring" alive="True"
Output
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 111
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:35:39 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 Porsche 924",
"description": "Eager and Daring",
"id": 5,
"name": "Cliffjumper"
}
Sharing the command prompt screenshot for your reference

3. Partially update an existing entry
http PATCH :8000/transformers/3/ alive="True"
Output
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Length: 151
Content-Type: application/json
Date: Sat, 23 Jan 2021 05:37:54 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
"alive": true,
"alternate_mode": "1979 VW Beetle",
"description": "Small, eager, and brave. Acts as a messenger, scout, and spy",
"id": 3,
"name": "Bumblebee"
}
Sharing the command prompt screenshot for your reference
In this section, we explored different types of class-based views provided by the Django REST Framework. We implemented views using APIView and explained different types of mixin classes. Finally, we revealed various types of generic class-based views and demonstrated how they avoid a huge amount of boilerplate code.
Similar Reads
FormView - Class Based Views Django
FormView refers to a view (logic) to display and verify a Django Form. For example, a form to register users at Geeksforgeeks. Class-based views provide an alternative way to implement views as Python objects instead of functions. They do not replace function-based views, but have certain difference
3 min read
Function based Views - Django Rest Framework
Django REST Framework allows us to work with regular Django views. It facilitates processing the HTTP requests and providing appropriate HTTP responses. In this section, you will understand how to implement Django views for the Restful Web service. We also make use of the @api_view decorator. Before
13 min read
Django Class Based Views
Class-Based Views (CBVs) allow developers to handle HTTP requests in a structured and reusable way. With CBVs, different HTTP methods (like GET, POST) are handled as separate methods in a class, which helps with code organization and reusability.Advantages of CBVsSeparation of Logic: CBVs separate d
6 min read
UpdateView - Class Based Views Django
UpdateView refers to a view (logic) to update a particular instance of a table from the database with some extra details. It is used to update entries in the database, for example, updating an article at geeksforgeeks. We have already discussed basics of Update View in Update View â Function based V
3 min read
ListView - Class Based Views Django
List View refers to a view (logic) to display multiple instances of a table in the database. We have already discussed the basics of List View in List View â Function based Views Django. Class-based views provide an alternative way to implement views as Python objects instead of functions. They do n
4 min read
TemplateView - Class Based Generic View Django
Django provides several class based generic views to accomplish common tasks. The simplest among them is TemplateView. It Renders a given template, with the context containing parameters captured in the URL. TemplateView should be used when you want to present some information on an HTML page. Templ
2 min read
Serializers - Django REST Framework
The serializers in the REST framework work very similarly to Djangoâs Form and ModelForm classes. The two major serializers that are most popularly used are ModelSerializer and HyperLinkedModelSerialzer. This article revolves around how to use serializers from scratch in Django REST Framework to adv
7 min read
Creating and Using Serializers - Django REST Framework
In Django REST Framework the very concept of Serializing is to convert DB data to a datatype that can be used by javascript. Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other conten
3 min read
DictField in serializers - Django REST Framework
In Django REST Framework the very concept of Serializing is to convert DB data to a datatype that can be used by javascript. Every serializer comes with some fields (entries) which are going to be processed. For example if you have a class with name Employee and its fields as Employee_id, Employee_n
4 min read
Basic Authentication - Django REST Framework
Authentication is a mechanism that provides access control based on the credentials associated with incoming requests. Django REST Framework provides several authentication schemes. In this section, let's look at the Basic Authentication in Django rest framework, i.e., authenticated against a user's
4 min read