You might be asking yourself, why should I even use class-based views when I can have more control of what is happening in function-based views? This section will answer that and highlight class-based views.

A view is a place where you can put the logic of your application. In general, we have 2 types of views in Django:

  • Function-based views
  • Class-based views

The major problem with function-based views is the lack of an easy way to extend them. You may see yourself using the same kind of code over and over again throughout your project which is not a good design principle.

In addition, function-based views use conditional branching inside a single view function to handle different HTTP methods which might make your code unreadable.

Class-based views aren’t a replacement for function-based views. However, they provide you with a way of writing views in an object-oriented fashion.

Anyways, we have the following class-based views in DRF:

  • APIView
  • GenericView
  • ViewSets

Class Based – APIView

APIView is similar to Django’s View class (It is actually an extension of it). You may have been using this approach to dispatch your requests to an appropriate handler like get() or post().

Setup for Class Based APIView

Let’s create a project first and setup URLs (skip this section if you are already aware of this setup).

#Create a fresh virtual environment

mkvirtualenv env (On creating, env will be activated automatically. Activate it if you navigate to a new tab.)

#Install Django 

pip install Django

#Go to your favourite directory and create a new project

django-admin startproject drinks

#Important step. Perform all the operations in this directory. When I say ‘project_template’ directory in future, it points to the directory present inside this, i.e,. project_directory/project_directory.

cd drinks

Lets create a sample app ‘core’.

python manage.py startapp core

Setting Up Project Settings.py

Add ‘core’ + rest_framework to installed apps in your settings.py files

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core',
    'rest_framework'
]

Working with models

Let’s build the model for our API. In this example, we are going to see how to store drinks

We are going to capture name and description details of each individual drink. 

Add the below code to the models.py inside the core folder.


from django.db import models

# Create your models here.


class Drink(models.Model):
  name=models.CharField(max_length=200)
  description = models.CharField(max_length=500)


  def __str__(self):
    return self.name+" "+self.description

Adding Serializers

Now its time to create a Serializers for API. 

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 content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

First, create a file called serializers.py and add the below code.


from rest_framework import serializers
from .models import Drink

class DrinkSerializer(serializers.ModelSerializer):
  class Meta:
    model= Drink
    fields = ['id', 'name', 'description']

in the fields, sections above you can use __all__ to add all the columns for serializations. If you want to capture individual ones you can pass a list of column names.

Updating the views.py– Class Based Views

Finally, let’s create Views.py

First we need to be able to fetch all the results by performing a GET and also should be able to add a new drink record.

The below code helps you fetch all records on GET and add new student details. The core of

class drink_list(APIView):
    def get(self, request, format=None):
        drinks = Drink.objects.all()
        serializer = DrinkSerializer(drinks, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = DrinkSerializer(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)

In the next scenario we are going to see how to work with individual student records using GET,PUT,DELETE

The PK here is the primary key column in your database which is ID in our case. 


class drink_detail(APIView):
    def get_object(self, id):
        try:
            return Drink.objects.filter(id=id).first()
        except Drink.DoesNotExist:
            raise Http404

    def get_object1(self, id):
        try:
            return Drink.objects.filter(id=id)
        except Drink.DoesNotExist:
            raise Http404

    

    def get(self, request, id=None):
        drinks = self.get_object1(id)
        serializer = DrinkSerializer(drinks, many=True)
        return Response(serializer.data)

    def put(self, request, id=None):

        drinks = self.get_object(id)
        serializer = DrinkSerializer(drinks, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)


    def delete(self, request, id=None):
        drinks = self.get_object(id)
        drinks.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Make sure to import all the necessary modules 

from .models import Drink
from .serializers import DrinkSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

Finally Urls.py

Last we will add the URLs to make sure we are able to hit it via the endpoints

Add/update the URL patterns in urls.py in StudentService

urlpatterns = [
    path('',views.drink_list.as_view()),
    path('<int:pk>/',views.drink_detail.as_view()),
]

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.