How to return custom JSON in Django REST Framework ?

27 Apr, 2021
In this article, we will create class-based views and combine this with the serializer class to return JSON representation for each HTTP request. For our class-based views, we will make use of a set of generic views, which help to achieve minimum lines code. 
Generic Classes and Viewsets
HTTP requests to interact with relationship resources
We will take advantage of generic class views to implement get, post, delete, put, and patch methods. For this, we need to make use of two generic class views from the rest_framework.generics module. They are:
ListCreateAPIView
RetrieveUpdateDestroyAPIView
The ListCreateAPIView class view implements the get method (retrieves a listing of a queryset) and post method (creates a model instance). And, the RetrieveUpdateDestroyAPIView class view implements get (retrieve a model instance), delete (delete a model instance), put (completely update a model instance), and patch (partially update a model instance).
In the Django REST framework, these two generic views are implemented as mixin classes. The ListCreateAPIView uses ListModelMixin and CreateModelMixin from rest_framework.mixins module and GenericAPIView from rest_framework.generics module. Let’s look at its declaration.
Python3
class ListCreateAPIView(mixins.ListModelMixin,                         mixins.CreateModelMixin, GenericAPIView):
The RetrieveUpdateDestroyAPIView uses RetrieveModelMixin, UpdateModelMixin and DestroyModelMixin from rest_framework.mixins module and GenericAPIView from rest_framework.generics module. Let’s look at its declaration.
Python3
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,                                    mixins.UpdateModelMixin,                                    mixins.DestroyModelMixin,                                    GenericAPIView):
Now, let’s get back to our RESTFul web service code and create the required set of Django class-based views. You can open the restpi\robots\views.py Python file and replace it with the below code.
Python3
from django.shortcuts import render  from rest_framework import genericsfrom rest_framework.response import Responsefrom rest_framework.reverse import reverse  from robots.models import RobotCategoryfrom robots.models import Manufacturerfrom robots.models import Robot  from robots.serializers import RobotCategorySerializerfrom robots.serializers import ManufacturerSerializerfrom robots.serializers import RobotSerializer  class ApiRoot(generics.GenericAPIView):    name = 'api-root'    def get(self, request, *args, **kwargs):        return Response({            'robot-categories': reverse(RobotCategoryList.name, request=request),            'manufacturers': reverse(ManufacturerList.name, request=request),            'robots': reverse(RobotList.name, request=request)            })                  class RobotCategoryList(generics.ListCreateAPIView):    queryset = RobotCategory.objects.all()    serializer_class = RobotCategorySerializer      class RobotCategoryDetail(generics.RetrieveUpdateDestroyAPIView):    queryset = RobotCategory.objects.all()    serializer_class = RobotCategorySerializer    name = 'robotcategory-detail'  class ManufacturerList(generics.ListCreateAPIView):    queryset = Manufacturer.objects.all()    serializer_class = ManufacturerSerializer    name = 'manufacturer-list'  class ManufacturerDetail(generics.RetrieveUpdateDestroyAPIView):    queryset = Manufacturer.objects.all()    serializer_class = ManufacturerSerializer    name = 'manufacturer-detail'          class RobotList(generics.ListCreateAPIView):    queryset = Robot.objects.all()    serializer_class = RobotSerializer    name = 'robot-list'  class RobotDetail(generics.RetrieveUpdateDestroyAPIView):    queryset = Robot.objects.all()    serializer_class = RobotSerializer    name = 'robot-detail'
Here the RobotCategoryList, ManufacturerList, and RobotList are the subclasses of generics.ListCreateAPIView; the RobotCategoryDetail, ManufacturerDetail, and RobotDetail are the subclasses of generics.RetrieveUpdateDestroyAPIView. Every subclass has a queryset attribute, serializer_class attribute, and a name attribute. The queryset attribute stores all the retrieved objects, the serializer_class attribute stores the serializer class, and the name attribute is used to identify each view.
Apart from class-based views, you can notice an ApiRoot class, which is a subclass of the rest_framework.generics.GenericAPIView. 
Python3
class ApiRoot(generics.GenericAPIView):    name = 'api-root'    def get(self, request, *args, **kwargs):        return Response({            'robot-categories': reverse(RobotCategoryList.name, request=request),            'manufacturers': reverse(ManufacturerList.name, request=request),            'robots': reverse(RobotList.name, request=request)            })
The ApiRoot class creates an end-point for the root of our RESTful web service that facilitates browsing the resource collection. The get method defines in this class returns a Response object that has the descriptive name and its URL. Here, it returns descriptive name and URL for robot categories list, manufacturers list, and robots list. 
Next, we need to specify the URL pattern in the regular expression to run a specific method for a class-based view defined in the views.py Python file. The client HTTP request has to match with this regular expression to run the methods in the views.py file. You can create the urls.py file in the restapi/robots and add the below code.
Python3
from django.conf.urls import urlfrom robots import views  urlpatterns = [    url(r'^robot-categories/$',        views.RobotCategoryList.as_view(),        name=views.RobotCategoryList.name),        url(r'^robot-categories/(?P<pk>[0-9]+)$',        views.RobotCategoryDetail.as_view(),        name=views.RobotCategoryDetail.name),        url(r'^manufacturers/$',        views.ManufacturerList.as_view(),        name=views.ManufacturerList.name),          url(r'^manufacturers/(?P<pk>[0-9]+)$',        views.ManufacturerDetail.as_view(),        name=views.ManufacturerDetail.name),        url(r'^robots/$',        views.RobotList.as_view(),        name=views.RobotList.name),        url(r'^robots/(?P<pk>[0-9]+)$',        views.RobotDetail.as_view(),        name=views.RobotDetail.name),        url(r'^$',        views.ApiRoot.as_view(),        name=views.ApiRoot.name),]
As a final step, we need to define the root URL configuration. You can open the restapi/restapi/urls.py Python file and replace it with the below code:
Python3
from django.conf.urls import url, include  urlpatterns = [    url(r'^', include('robots.urls')),]
It is time to test our code by composing and sending the various HTTP requests. Here, we will take advantage of both the HTTPie command and the CURL command.
Let’s compose and send an HTTP Post request to create a new robot category. The HTTPie command is:
http POST :8000/robot-categories/ name=”Articulated Robots” notes=”Flexibility, dexterity, and reach make articulated robots ideally suited for tasks that span non-parallel planes”
Output:
Robot Category Post Request (HTTPie)
Let’s create another robot category using the curl command. 
curl -iX POST -H “Content-Type: application/json” -d “{\”name\”:\”SCARA Robots\”, \”notes\”:\”A Selective Compliance Articulated Robot Arm (SCARA) is a good and cost-effective choice for performing operations between two parallel planes\”}” localhost:8000/robot-categories/
Output:
Robot Category POST request (cURL)
Let’s compose a GET request to retrieve all robot categories. The HTTPie command is:
http :8000/robot-categories/
Output:
Robot Category GET request (HTTPie utility command)
The equivalent curl command is
curl -iX GET localhost:8000/robot-categories/
Output:
GET request (cURL)
The HTTPie command to retrieve a robot category is:
http :8000/robot-categories/1
Output:
GET request (single category)
The equivalent curl command is:
curl -iX GET localhost:8000/robot-categories/1
Let’s compose and send an HTTP POST request to create a manufacturer. The HTTPie command is:
http :8000/manufacturers/ name=”FANUC Global” rating=4 notes=”The automation specialist and industrial robot manufacturer”
Output:
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 219
Content-Type: application/json
Date: Mon, 16 Nov 2020 06:36:12 GMT
Location: http://localhost:8000/manufacturers/1
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
{
    “entry_date”: “2020-11-16T06:36:12.449074Z”,
    “robots”: [],
    “name”: “FANUC Global”,
    “notes”: “The automation specialist and industrial robot manufacturer”,
    “pk”: 1,
    “rating”: 4,
    “url”: “http://localhost:8000/manufacturers/1”
}
Let’s create another manufacturer using the curl command.
curl -iX POST -H “Content-Type: application/json” -d “{\”name\”:\”ABB\”, \”rating\”:5, \”notes\”:\”Focused in Electrification, Industrial Automation, Robotics, Discrete Automation and Motion\”}” localhost:8000/manufacturers/
Output:
HTTP/1.1 201 Created
Date: Mon, 16 Nov 2020 06:49:43 GMT
Server: WSGIServer/0.2 CPython/3.7.5
Content-Type: application/json
Location: http://localhost:8000/manufacturers/2
Vary: Accept, Cookie
Allow: GET, POST, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Length: 242
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
{“url”:”http://localhost:8000/manufacturers/2′′,”pk”:2,”name”:”ABB”,”rating”:5,
“notes”:”Focused in Electrification, Industrial Automation, Robotics, Discrete Automation 
and Motion”,”entry_date”:”2020-11-16T06:49:43.108992Z”,”robots”:[]}
Let’s compose a request to retrieve a manufacturer. The HTTPie command is:
http :8000/manufacturers/2
Output:
Retrieve a single manufacturer
The equivalent curl command is: 
curl -iX GET localhost:8000/manufacturers/2
We have populated the robot category and manufacturer details. Now, let’s compose and send a POST request to add robot details. The HTTPie command is 
http POST :8000/robots/ name=”FANUC M-710ic/50′′ robot_category=”Articulated Robots” currency=”USD” price=37000 manufacturer=”FANUC Global” manufacturing_date=”2019-10-12 00:00:00.000000+00:00′′ add_details=”Axes 6, Payload 50 KG, Reach 2050 MM”
Output:
Robot Entry (HTTP Utility Pie command)
Let’s compose a curl command to create a new entry.
curl -iX POST -H “Content-Type: application/json” -d “{\”name\”:\”SR-3iA\”, \”robot_category\”:\”SCARA Robots\”, \”currency\”:\”USD\”, \”price\”:37000, \”manufacturer\”:\”FANUC Global\”, \”manufacturing_date\”:\”2019-10-12 00:00:00.000000+00:00\”, \”add_details\”:\”Axis 4, Payload 3 KG, Reach 400 MM\”}” localhost:8000/robots/
Output:
Let’s add a few more entries in Robot. The HTTPie commands are:
http POST :8000/robots/ name=”IRB 120′′ robot_category=”Articulated Robots” currency=”USD” price=14500 manufacturer=”ABB” manufacturing_date=”2020-05-10 00:00:00.000000+00:00′′ add_details=”Axes 6, Payload 3 KG, Reach 0.58m”
http POST :8000/robots/ name=”IRB 910SC” robot_category=”SCARA Robots” currency=”USD” price=25000 manufacturer=”ABB” manufacturing_date=”2020-05-10 00:00:00.000000+00:00′′ add_details=”Axes 4, Payload 6 KG, Reach 0.65m”
Let’s look into the Robot, Robot Category, and Manufacturer list. 
http :8000/robots/
Robot List
http :8000/robot-categories/
Robot Category List
http :8000/manufacturers/
Manufacturer List
In robot categories and manufacturer entry, you can notice that the robots are mentioned in its URL form. 
Now let’s compose PUT, PATCH, and DELETE requests. We will add a new robot category (Test Category) and manufacturer (Test Manufacturer). The HTTPie command as follows:
http POST :8000/robot-categories/ name=”Test Category” notes=”Test”
http POST :8000/manufacturers/ name=”Test Manufacturer” rating=1 notes=”Test”
Let’s add a few robots that belong to the Test Category and Test Manufacturer. The HTTPie command as follows:
http POST :8000/robots/ name=”TEST 1′′ robot_category=”Test Category” currency=”USD” price=37000 manufacturer=”Test Manufacturer” manufacturing_date=”2019-10-12 00:00:00.000000+00:00′′ add_details=”Test”
http POST :8000/robots/ name=”TEST 2′′ robot_category=”Test Category” currency=”USD” price=37000 manufacturer=”Test Manufacturer” manufacturing_date=”2019-10-12 00:00:00.000000+00:00′′ add_details=”Test”
http POST :8000/robots/ name=”TEST 3′′ robot_category=”Test Category” currency=”USD” price=37000 manufacturer=”Test Manufacturer” manufacturing_date=”2019-10-12 00:00:00.000000+00:00′′ add_details=”Test”
Let’s check the entries in the database using the below psql command. 
select * from robots_robot;
Output:
You can notice that new entries are added to our database. 
PUT HTTP verb
Now let’s edit the last entry named TEST 3, which has 11 as the primary key, using the PUT HTTP verb.
The HTTPUtility Pie command is:
http PUT :8000/robots/11  name=”TEST 3′′ robot_category=”Test Category” currency=”USD” price=12000 manufacturer=”Test Manufacturer” manufacturing_date=”2020-10-12 00:00:00.000000+00:00′′ add_details=”Test3′′
Output:
The equivalent curl command is
curl -iX PUT -H “Content-Type: application/json” -d “{\”name\”:\”TEST 3\”, \”robot_category\”:\”Test Category\”, \”currency\”:\”USD\”, \”price\”:12000, \”manufacturer\”:\”Test Manufacturer\”, \”manufacturing_date\”:\”2020-10-12 00:00:00.000000+00:00\”, \”add_details\”:\”Test3\”}” localhost:8000/robots/11
PATCH HTTP Verb
Let’s partially edit the resource that has primary key 11. The HTTPie command for PATCH request is:
http PATCH :8000/robots/11  price=15000 add_details=”Test3 Patch”
Output:
The equivalent curl command is:
curl -iX PATCH -H “Content-Type: application/json” -d “{ \”price\”:15000, \”add_details\”:\”Test3 Patch\”}” localhost:8000/robots/11
DELETE HTTP Verb
Now, let’s delete the entry that has primary key 11 using DELETE HTTP Verb. The HTTPie command is:
http DELETE :8000/robots/11
Output:
The equivalent curl command is 
curl -iX DELETE localhost:8000/robots/11
Now, we need to check what happens if a robot category is deleted. According to our code, if a category is deleted, then all the robots that belong to the particular category should also be cleared. Let’s delete our Test Category (the primary id 3). The HTTPie command is
http DELETE :8000/robot-categories/3
Output:
Let’s look at the robot table. In total, we added 3 robots (Test 1, Test 2, and Test 3) that belong to Test Category. The robot that has primary id 11 (Test 3) is already deleted using delete request. The remaining two robots with primary id 9 (Test 1) and 10 (Test 2) exist in the database. Since we deleted the Test Category, automatically the other two robots will be cleared from the table. Let’s check the database using the psql command.
select * from robots_robot;
Output:
You can notice that the robots belong to Test Category are cleared successfully. This is made possible with the help of the code, on_delete=models.CASCADE, mentioned while defining the robot category as a foreign key in the robot model.
In this article, we learned about generic class views to implement HTTP requests. For this, we used two generic class views from the rest_framework.generics module, ListCreateAPIView and RetrieveUpdateDestroyAPIView. And also we composed different HTTP requests to interact with related resources.
Django-REST
Python Django
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
How to Install PIP on Windows ?
Python Classes and Objects
Python OOPs Concepts
Introduction To PYTHON
How to drop one or multiple columns in Pandas Dataframe
Python | os.path.join() method
Check if element exists in list in Python
How To Convert Python Dictionary To JSON?
Python | Get unique values from a list
Python | datetime.timedelta() function