Build REST API in Django Using Rest Framework [Function based views]

1 . Introduction

In this post, we are going to learn about function based views in Django. Django has two types of views; function-based views (FBVs), and class-based views (CBVs). Django originally started out with only FBVs, but then added CBVs as a way to templatize functionality so that you didn’t have to write boilerplate (i.e. the same code) code over and over again.



2. Setup

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.py startproject StudentService

#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 StudentService
Lets create a sample app 'students'.

python manage.py startapp students

3. Setting Up Project Settings.py
Add 'students' + 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',
    'students',
    'rest_framework'
]

Modify your Database settings as well. We are going to work with MYSQL Database

Add this to your settings.py file


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'studentdb',
        'USER': 'root',
        'PASSWORD': ''
    }
}

4. Working with models

Let's build the model for our API. In this example, we are going to see how to store students scores for examinations.

We are going to capture ID, NAME & score details of each individual student. 

Add the below code to the models.py inside the student's folder.


from django.db import models

# Create your models here.

class Students(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length = 20)
    score = models.DecimalField(max_digits=10,decimal_places=3)

    def __str__(self):
        return self.id+self.name+self.score

5. 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 students.models import Students

class StudentSerializers(serializers.ModelSerializer):
    class Meta:
        model = Students
        fields = ["id","name","score"]

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.


6. Updating the views.py

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 student record.

The below code helps you fetch all records on GET and add new student details. The core of this functionality is the api_view decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data: 



@api_view(['GET','POST'])
def students_list(request):
    if request.method == 'GET':
        students = Students.objects.all()
        serializers = StudentSerializers(students,many=True)
        return Response(serializers.data)

    elif(request.method == 'POST'):
        serializers = StudentSerializers(data=request.data)
        if serializers.is_valid():
            serializers.save()
            return Response(serializers.data,status=status.HTTP_201_CREATED)
        return Response(serializers.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. 


api_view(['GET','PUT','DELETE'])
def students_details(request,pk):
    try:
        student = Students.objects.get(pk=pk)
    except Students.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializers = StudentSerializers(Students)
        return Response(serializers.data)

    elif request.method == 'PUT':
        serializers = StudentSerializers(Students,request.data)
        if serializers.is_valid():
            serializers.save()
            return Response(serializers.data)
        return Response(serializers.errors,status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        Students.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
Make sure to import all the necessary modules 


from students.models import Students
from students.serializers import StudentSerializers
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view

7. 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('admin/', admin.site.urls),
    path('students/', views.students_list),
    path('students/', views.students_details),

]


This function based views is very easy to implement and it’s very useful but the main disadvantage is that on a large Django project, usually a lot of similar functions in the views. If all objects of a Django project usually have CRUD operations so this code is repeated again and again unnecessarily and this was one of the reasons that the class-based views and generic views were created for solving that problem.

Conclusion:

We saw how to use the function based views in this post while there are other types of views as well which we will cover in upcoming posts. if you want to know if function based views are best among all then it all depends on the context and the needs. As I mentioned in the beginning of this post, class-based views does not replace function-based views. There are cases where function-based views are better. In other cases, class-based views are better.


Hey I'm Venkat
Developer, Blogger, Thinker and Data scientist. nintyzeros [at] gmail.com I love the Data and Problem - An Indian Lives in US .If you have any question do reach me out via below social media