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:
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
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.)
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.
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
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
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.