Writing class based Views in Django REST Framework

This post is in continuation with our previous post “Developing REST API using functions in DRF application views”, in the previous post, we used functions to write the views. In this post, we will show how you can use class instead of functions to write the views.

Since we have explained all the things in our previous post “Developing first REST API using Django Rest Framework ( DRF )” , you can find the code for this post at github https://github.com/lynxbee/drf_api_class_based_views and in this post, we will just explain the related changes..

$ vim helloproject/helloapp/views.py
from django.shortcuts import render

from rest_framework import viewsets
from rest_framework import status

from rest_framework.parsers import JSONParser
from rest_framework.views import APIView

from django.http import Http404
from django.http import HttpResponse, JsonResponse

from helloproject.helloapp.models import UserInfo
from helloproject.helloapp.serializers import UserInfoSerializer

class usersClassView(APIView):
    def get(self, request, format=None):
        users = UserInfo.objects.all()
        serializer = UserInfoSerializer(users, many=True)
        return JsonResponse(serializer.data,safe=False)

    def post(self, request, format=None):
        serializer = UserInfoSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=status.HTTP_201_CREATED)
        return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class user_by_pk(APIView):
    def get_object(self, pk):
        try:
            return UserInfo.objects.get(pk=pk)
        except UserInfo.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        users = UserInfo.objects.filter(pk=pk)
        serializer = UserInfoSerializer(users, many=True)
        return JsonResponse(serializer.data, safe=False)

    def post(self, request, format=None):
        data = JSONParser().parse(request)
        serializer = UserInfoSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def put(self, request, pk, format=None):
        user = UserInfo.objects.get(pk=pk)
        data = JSONParser().parse(request)
        serializer = UserInfoSerializer(user, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

As you can see above, we have defined two class “usersClassView” which just shows the list of all the users and second, “user_by_pk” which is used to identify the single user.

Now, we need to map this views to urls so we can do http GET and http POST to this urls.

$ vim helloproject/helloapp/urls.py
from django.urls import include, path

from helloproject.helloapp import views

urlpatterns = [
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    path('users/', views.usersClassView.as_view()),
    path('user/<int:pk/>', views.user_by_pk.as_view()),
]

Notice here, we have declared two api urls, 1. ” http://127.0.0.1:8000/users/ ” mapped to views.py “usersClassView” class and “http://127.0.0.1:8000/user/user_primary_key” mapped to “user_by_pk” class of views.py

Now, run the server and when you visit two API’s http://127.0.0.1:8000/users/ and http://127.0.0.1:8000/user/primary_key/ you will see it showing empty json… lets do some http post of users api using below script,

#!/bin/bash

API_URL="http://127.0.0.1:8000/users/"

username="lynxbee"
email="social(at)lynxbee.com"
age="35"

data="{\"username\":\"$username\",\"email\":\"$email\",\"age\":\"$age\"}"
echo $data

curl -v -k -H "\"Accept: application/json\"" -H "\"Content-Type:application/json\"" -d $data $API_URL

this script does http POST to populate data to API, now lets say you pushed two entries, then you can see the json as,

[{
	"id": 1,
	"username": "lynxbee",
	"email": "social(at)lynxbee.com",
	"age": "35"
}, {
	"id": 2,
	"username": "lynxbee",
	"email": "social(at)lynxbee.com",
	"age": "35"
}]

Now, using our second API to get individual information using primary key, we need to do http GET using indivial / second API, type http://192.168.0.106:8000/user/2/

here, as you can see “http://192.168.0.106:8000/user/2/” API is mapped to

path('user/<int:pk/>', views.user_by_pk.as_view())

from urls.py and same is mapped to views.py. notice here, “int:pk” appends to number to the API request i.e. “user/2” as seen above.

Leave a Comment