How to Serialize Data With Django REST Framework

31083 VIEWS

· ·

In this day and age, when APIs are so popular, developers must be cautious about how they serialize and deserialize data, as well as how secure their data is. Companies are constantly working on ways to develop dynamic applications that provide similar functionalities in both web and mobile platforms. As a result, we have APIs that promote the centralization of business logic in one place. This saves money and time because development, testing, and maintenance time are reduced. 

NOTE: This article is for mid to senior level developers who have a good understanding of using the Django framework and are interested in familiarizing themselves with the Django REST framework. 

By the end of this article, you should be able to use Django REST Framework to serialize your data or any nested fields in Django models and have an API endpoint for your data. This skill has a steep, short learning curve, so get ready to dive right in.

What is Data Serialization?  

Data Serialization is the process of converting data from one format to another readable with frontend frameworks. Serialized data is commonly converted to its JSON (a format that encodes objects in a string) pendant. Deserialization just does the opposite.

Django is one of the upcoming web frameworks which comes along with its REST framework. REST stands for REpresentational State Transfer. It describes an architecture which is used for the purpose of creating APIs for data communication. Django REST offers serialization and deserialization of data and above that it offers data validation making sure that the type of data that is stored correctly corresponds to what is defined in the models. This is very convenient for any developer who would be considering creating an API.

How to Serialize Data With DRF

The Django Rest Framework (DRF) is a strong and adaptable set of tools for creating APIs. Data can be serialized in DRF in just a few different methods, namely using Serializers class and models Serializers. 

Let’s dive in and serialize data using DRF right away. 

Step 1: Creating Django Application

We’ll start by developing a straightforward Django project. If you are reading this, I will assume that you are familiar with  the basics of Django; if not, see the original Django documentation for more details.

 Setting up the Virtual Environment
Python3 -m venv virtual

Activating the virtual environment is as easy as typing the below commands in the terminal.

For Linux:

source virtual/bin/activate

For Windows:

virtual\Scripts\activate

The below image represents our project folder structure of the created project and application. 

With our virtual environment activated, the next step is to install the REST framework with the command below:

pip install djangorestframework

After installation, the next step is to set up our application to work with the Django REST framework. We’ll add the rest framework under the INSTALLED APPS part of the settings.py file in the project folder, and it should resemble the snapshot below when finished:

As demonstrated below, we provide paths to links that return the appropriate view function when we submit requests to the API and app in the project’s urls.py file.

We also need to create a serializers.py file which will serialize our classes. The setup should look like the image below.

Step 2: Creating Our Models

The next step is to create the models that we want to be serialized. In my case I have two classes: Student and Classroom. In the student class we’ve inherited the default Django User models class. What that means is that in the classroom class with the student as a foreign key, we have a deeply nested object. The structure should look something like:

 

from statistics import mode
import uuid
from django.contrib.auth.models import User
from django.db import models
from cloudinary.models import CloudinaryField
 
GENDER = (
    ('Male','MALE'),
    ('Female','FEMALE'),
    ('Other','OTHER'),
)
 
TYPES =(    
    ('Python', 'PYTHON'),
    ('Java', 'JAVA'),
)
 
class Student(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    account = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    avatar = CloudinaryField('image', blank=True, null=True)
    gender = gender = models.CharField(choices=GENDER, max_length=55)
    location = models.CharField(max_length=55)
    joined_on = models.DateTimeField(auto_now_add=True)
    stack = models.CharField(choices=TYPES, max_length=55)
   
    def __str__(self):
        return self.account.username
   
class Classroom(models.Model):
    student = models.ForeignKey(Student, blank=True, null=True, on_delete=models.CASCADE, related_name='student_details')
    classroom = models.CharField(blank=True, null=True, max_length=85)
    mentor = models.CharField(blank=True, null=True, max_length=85)
   
    def __str__(self):
        return self.classroom

models.py file 

With our models ready, the next thing is to create a local database for holding our data and testing. In my case I’ll be using SQLite3 which comes pre-defined when setting up a Django project. We’ll migrate our models classes to the database with the commands below:

python manage.py makemigrations
python manage.py migrate
Step 3: Serializing the Data With Django Rest Framework

Now we are ready to start serializing our model classes. In the serializer.py file, we import our model classes from our models.py file and a serialization class from DRF. See image below:

from rest_framework import serializers
from .models import *

In our model file, we see that we have a student class with a user field as a foreign key from the default Django User class. Without creating the UserSerialization class, the data representation of the user details will default to showing only the ID, instead of the actual data. Let’s create a StudentSerializer class in order to demonstrate this. 

In the StudentSerializer class above, we use the DRF ModelsSerializer class to serialize whatever data we will have in our models. The next step is to create a view function to render our data.

Step 4: CRUD Methods & View Function

In our views, we have imported the classes we serialized from serializers.py file. And then we imported APIView from DRF so that the requests and responses that are made to the endpoints are handled by the REST framework. 

In the StudentView class, we’ve defined our CRUD operations. In our case we have the GET all students, or GET student by ID if an ID parameter is present in the request. The other method we’ve defined is a POST request to handle posting new data to our endpoints. 

The views.py file looks as follows:

from django.shortcuts import render,get_object_or_404
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from .models import *
from .permissions import *
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
 
class AllStudents(APIView):
 
    def get(self, request, format=None):
        content = {
            'user': str(request.user),  # `django.contrib.auth.User` instance.
            'auth': str(request.auth),  # None
        }
        return Response(content)
   
    def post(self, request):
        serializer = StudentSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
        else:
            return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
   
   
    def get(self, request, uuid=None):
        if uuid:
            student = Student.objects.get(uuid=uuid)
            serializer = StudentSerializer(student)
            return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
 
        students = Student.objects.all()
        serializer = StudentSerializer(students, many=True)
        return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)  
 
    def put(self, request, uuid=None):
        student = Student.objects.get(uuid=uuid)
        serializer = StudentSerializer(student, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({"status": "success", "data": serializer.data})
        else:
            return Response({"status": "error", "data": serializer.errors})
 
 
    def delete(self, request, uuid=None):
        student = get_object_or_404(Student, uuid=uuid)
        student.delete()
        return Response({"status": "success", "data": "student Deleted"})
   
 
class MyUsers(APIView):
   
    def get(self, request, pk=None):
        if pk:
            user = User.objects.get(id=pk)
            serializer = UserSerializer(user)
            return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
 
        user = User.objects.all()
        serializer = UserSerializer(user, many=True)
        return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
   
    def post(self, request):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
        else:
            return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
   
   
    def put(self, request, pk=None):
        user = User.objects.get(id=pk)
        serializer = UserSerializer(user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({"status": "success", "data": serializer.data})
        else:
            return Response({"status": "error", "data": serializer.errors})
Step 5: Creating the API Endpoints

Lastly in the app urls.py file we add the specific endpoint that will render our data.

from .views import *
from django.urls import path
from . import views
 
 
urlpatterns=[
    path('', views.index, name='index'),
    path('students', AllStudents.as_view()),
    path('students/<str:uuid>', AllStudents.as_view())  
]

When we run our server and open our Postman with GET://students, we get an empty array. This is because our database STUDENTS Table is empty.

To add student data, we must first create a superuser account in the Django admin panel. We then import and register the model classes in the admin.py file so they can be seen on the admin site interface.

python manage.py createsuperuser --username admin --email [email protected]

Once the student data has been saved, a new API request must be made in Postman to obtain a different response. Now that the data we submitted has been serialized, any front-end framework can use it.

Step 6: Serializing Nested Data

If we take a close look at the account i.e the User class, we don’t have the user data that we can use to identify a specific student, since this is a nested data. In order to have our serialized data show up, we need to create the UserSerializer class and then specify in our studentSerializer class that the “account” column is a representation of the UserSeriazer class as show below:

In the UserSerializer class, we’ve defined a function that will hash our password, and we have specified the fields we want to be visible in our requests and responses. Now if we send another GET request using postman, we get a very detailed response.

After making a POST request the students’ API endpoint, you should have an output similar to the image below.

 

If you are getting an error when writing a nested field  or the “create” function, add the below function in the student serializer class. This should fix the problem. Check below image for further details.

Conclusion

As already established, the Django REST Framework would be extremely useful to any developer who wants to create a secure API or simply serialize data. Data serialization helps in securing application data because it requires authentication and authorization to avoid data manipulation when using frontend frameworks.

Find the complete source code in this repository.


Faith Kilonzi is a full-stack software engineer, technical writer, and a DevOps enthusiast, with a passion for problem-solving through implementation of high-quality software products. She holds a bachelor’s degree in Computer Science from Ashesi University. She has experience working in academia, fin-tech, healthcare, research, technology, and consultancy industries in both Kenya, Ghana, and in the USA. Driven by intellectual curiosity, she combines her passion for teaching, technology, and research to create technical digital content.


Discussion

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar