You are on page 1of 7

Developers How To

Generating APIs Using Django


Rest Framework with Insomnia
This article gives the fundamentals of generating APIs using Django Rest
Framework with Insomnia. It’s aimed at absolute beginners.

T
his article will familiarise Pip can be defined as an installation Django project. To state bluntly, virtual
you with the basic structural manager for packages/libraries that are environments are environments that
layout and features that come written in Python. Let’s download a file can have distinct versions of packages/
with creating a Django project for API called get-pip.py: libraries installed within them,
generation. It will help you understand respectively. Let me explain that with
what models, serialisers and views curl https://bootstrap.pypa.io/get-pip. an example. We are in April 2022, and
are, how they are interconnected, py -o get-pip.py we intend to create a project (to be dealt
and how we can use Insomnia to test with in VS Code). Let’s say the latest
the functioning of CRUD (create, To install pip, give the following version of Python is 3.1 (which we have
read, update and delete) operations command: installed in our system and no virtual
on our APIs. environments have been created) having
python get-pip.py libraries a, b, c, d, e and f. Assume
Initial setup that our project requires libraries a, b
You will be required to use the and c, all of which are in Python 3.1;
Note: Figure 1 shows pip as
command prompt or carry out the initial hence our project will work without any
being uninstalled first and then
steps needed to create a Django project. reinstalled, because I already had hindrances.
Check the version of Python you have pip installed on my system. Now let’s say Python’s new version
installed on your system: 3.2 comes out a few weeks or a few
Now let us understand what ‘virtual months later which has libraries a,
python --version environments’ are before we create a d, e, f, g and h. We install this new

64  |  MAY 2022  |  OPEN SOURCE FOR YOU  |  www.OpenSourceForU.com


How To Developers

within the directory:

Syntax for creating a directory: mkdir


(name of directory)
Syntax for accessing a created
directory: cd (name of directory)
Syntax for creating a django project:
django-admin startproject osfyproject1

(venv1) C:\Users\kamil>mkdir osfydir


(venv1) C:\Users\kamil>cd osfydir
(venv1) C:\Users\kamil\osfydir>django-
admin startproject osfyproject1

Now that the Django project has


been created, let us run the server
within our newly created project. The
command prompt is:
Figure 1: The command prompt
(venv1) C:\Users\kamil\osfydir>cd
version on our system (having created environment immediately), type: osfyproject1
no virtual environments). Our project (venv1) C:\Users\kamil\osfydir\
will not function properly now since pip install virtualenvwrapper-win osfyproject1>python manage.py runserver
it required libraries b and c to do so,
which are now not present in 3.2. This To create a virtual environment Watching for file changes with
is where virtual environments come in. ‘venv1’, give the following command: StatReloader
Assume we create a virtual environment Performing system checks...
‘venv1’. Within this, we’ll install mkvirtualenv venv1
Python 3.1 and create our project. In System check identified no issues (0
another virtual environment ‘venv2’, silenced).
Note: The ‘(venv1)’ observed
we can install Python 3.2. Note that
towards the left of the latest
the project we created in ‘venv1’ will command line indicates that we are You have 18 unapplied migration(s).
not work in ‘venv2’ since ‘venv2’ has inside a virtual environment. Your project may not work properly
Python 3.2 installed within it, which until you apply the migrations for
does not encompass all the libraries that Now, install Django: app(s): admin, auth, contenttypes,
the project requires. The purpose of this sessions.
elaborate explanation is to give you an pip install Django Run ‘python manage.py migrate’ to apply
idea of how virtual environments work. them.
To install a virtual environment Next, create a new directory, access April 12, 2022 - 16:18:22
wrapper (does not create a virtual it and then create a Django project Django version 4.0.3, using settings

Figure 2: Command prompt involving creation of virtual environment ‘venv1’

www.OpenSourceForU.com  |  OPEN SOURCE FOR YOU  | MAY 2022  |  65


Developers How To

C:\Users\kamil\osfydir\
osfyproject1>workon venv1
(venv1) C:\Users\kamil\osfydir\
osfyproject1>

We now create an app within our


project. Let’s say that your ‘project’ is a
website on the whole and the ‘apps’ are
specific Web pages within the website.
Since you wish to write the logics for
Figure 3: Installation of Django APIs of different Web pages, you will
want to write them in their respective
views.py files. You will understand as
we go further.

(venv1) C:\Users\kamil\osfydir\
osfyproject1>python manage.py startapp
firstapp

(venv1) C:\Users\kamil\osfydir\
osfyproject1>

Instead of getting an overview


of the various purposes the different
files within the app and the project
serve, which might confuse you in
the beginning, let’s go about it step-
by-step as we move along the path of
obtaining the end goal of our task. First,
let’s create a table in our database with
different kinds of fields. But hang on,
Figure 4: Contents of the project in VS Code we first need to establish a connection
with the database in order to create
‘osfyproject1.settings’ a table within it. We will be using
Starting development server at pgAdmin (PostgreSQL) for our task.
http://127.0.0.1:8000/ We first need to establish a
Quit the server with CTRL-BREAK. connection between our project
and the osfyproject1 database. We
The http://127.0.0.1:8000/ need psycopg2 to do so. Let’s install
observed in the second last line of psycopg2 by entering a command
the above code is the base URL of all within the prompt in VS Code. The
the operations we wish to perform. following section of code shows the
We will observe how we generate output of the installation operation.
separate URLs as an extension of this
for carrying out CRUD operations, in (venv1) C:\Users\kamil\osfydir\
later sections. osfyproject1>pip install psycopg2
Now let’s head to VS Code and Figure 5: Updated file explorer in VS Code Collecting psycopg2
open our project by selecting it within Using cached psycopg2-2.9.3-cp310-
the directory, the file path of which is Microsoft Windows [Version cp310-win_amd64.whl (1.2 MB)
C:\Users\kamil\osfydir. 10.0.19043.1586] Installing collected packages: psycopg2
Let us activate our virtual environment (c) Microsoft Corporation. All rights Successfully installed psycopg2-2.9.3
within the terminal of VS Code: reserved. WARNING: You are using pip version

66  |  MAY 2022  |  OPEN SOURCE FOR YOU  |  www.OpenSourceForU.com


How To Developers

21.3.1; however, version 22.0.4 is }


available. }
You should consider upgrading via the
‘C:\Users\kamil\Envs\venv1\Scripts\ The ‘PASSWORD’ will be the
python.exe -m pip install --upgrade password you set when you installed
pip’ command. PostgreSQL on your system (mine was
simply ‘password’ itself).
Let us now create a table in our Another section within ‘settings.
database. These ‘tables’ are referred py’ which requires an addition is the
to, as per the terminology of a Django ‘INSTALLED_APPS’ section.
project, as ‘models’, and are defined
within the ‘models.py’ file in the app. INSTALLED_APPS = [
Within ‘models.py’ of firstapp, let’s ‘firstapp’,
write the following: ‘django.contrib.admin’,
‘django.contrib.auth’,
from django.db import models ‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
# Create your models here. ‘django.contrib.messages’,
‘django.contrib.staticfiles’,
class Studentinfo(models.Model): ]
First_name=models.CharField(max_len
gth=50,blank=False,null=False) Kindly add ‘firstapp’ in the
Last_name=models.CharField(max_leng above list.
th=50,blank=False,null=False) Now, we must send our table to the
Student_ID=models.IntegerField(blan database, which in this terminology
k=False,null=False) is ‘migrating’ our models. Migrating
Email_ID=models.EmailField(blank=Fa our defined model to our PostgreSQL
lse,null=False) database involves two simple steps:

Our idea is to create a simple Figure 6: Newly created database in pgAdmin (venv1) C:\Users\kamil\osfydir\
table/model taking in the information osfyproject1>python manage.py
of a student. The fields ‘First_name’ ‘default’: { makemigrations
and ‘Last_name’ are character fields, ‘ENGINE’: ‘django.db.backends. Migrations for ‘firstapp’:
which allow a maximum length of sqlite3’, firstapp\migrations\0001_initial.py
50 characters. The ‘Required=True’ ‘NAME’: BASE_DIR / ‘db. - Create model Studentinfo
parameter implies that you cannot sqlite3’,
discard this field (this will be covered in } The ‘makemigrations’ step
a case scenario later). The ‘null=False’ } automatically creates a file called
means that these fields will not accept ‘0001_initial.py’ in the migrations
null values. There are many different By default, it considers sqlite3 as folder within our ‘firstapp’. This file
types of fields and parameters for its database platform, but in our case, has code written in Python, which
Django models, which you can find in we are using PostgreSQL. The modified inculcates the definition of our
the official documentation of Django. section should appear like this: model in a way that PostgreSQL will
We now need to ‘send’ our defined understand. Let’s take a peek at how
model/table to our database. For DATABASES = { this looks:
this, let’s make a few changes to the ‘default’: {
‘DATABASES’ section within the ‘ENGINE’: ‘django.db.backends. from django.db import migrations,
settings.py file of ‘osfyproject1’ in VS postgresql’, models
Code. The pre-existing section looks as ‘NAME’: ‘osfyproject1’,
follows: ‘USER’:’postgres’, class Migration(migrations.Migration):
‘PASSWORD’:’password’, initial = True
DATABASES = { ‘HOST’:’localhost’, dependencies = [

www.OpenSourceForU.com  |  OPEN SOURCE FOR YOU  | MAY 2022  |  67


Developers How To

Figure 7: Glimpse of our newly-created model


Create a new file within ‘firstapp’
] called ‘serializers.py’ and write the
operations = [ following: {‘First_name’: ‘Kamil’, ‘Last_name’:
migrations.CreateModel( ’Khan’, ‘Student_ID’: 085, ‘Email_ID’:
name=’Studentinfo’, from rest_framework import serializers ‘kamilpaigah@gmail.com’}
fields=[ from .models import Studentinfo
(‘id’, models. The aim of covering the above code
BigAutoField(auto_created=True, class Studentserializer(serializers. was to provide a practical explanation
primary_key=True, serialize=False, ModelSerializer): of the definition found on the Web,
verbose_name=’ID’)), class Meta: but since we will be using Insomnia
(‘First_name’, models. model=Studentinfo here onwards, we will not be required
CharField(max_length=50)), fields=’__all__’ to enter data in the format we just
(‘Last_name’, models. observed. We will be entering data in
CharField(max_length=50)), A serializer is defined on the Web JSON format itself. In simple terms,
(‘Student_ID’, models. as follows: “Serializers allow complex a serializer creates a serializer class,
IntegerField()), data such as query sets and model which maps the fields of the model
(‘Email_ID’, models. instances to be converted to native it is associated with. You may ask, if
EmailField(max_length=254)), Python datatypes that can then be easily that’s the case, what’s the difference
], rendered into JSON.” Simply put, it between a model and a serializer? From
), converts the object(s) entered into what I have observed, a serializer has
] JSON format. the capability to check the validity of
the data entered, such as checking if the
For the next step, we simply use the Let’s take an example. Say, we value entered for field(s) is of the type
keyword ‘migrate’, which results in a have a simple logic for entering new defined in the model; if not, it will show
table called ‘Studentinfo’ being created data into the database in our ‘views. errors. Now let’s move on to views.py,
in our database: py’, which does not include checks wherein we will cover the logic for
for any errors. Now, if we were to ‘Create’ and ‘Read’.
(venv1) C:\Users\kamil\osfydir\ make an entry into our table in the
osfyproject1>python manage.py migrate format below: from firstapp.models import Studentinfo
from .serializers import
The output of the above command # create a student object Studentserializer
shows around 15 items being checked >>> student = Studentinfo(First_ from rest_framework.response import
as ‘OK’. If you take a look at the name=’Kamil’, Last_name=’Khan’, Response
‘Tables’ tab in the ‘osfyproject1’ Student_ID=085, Email_ID=’kamil123@ from rest_framework import status
database, you will find a ‘firstapp_ gmail.com’) # Create your views here.
studentinfo’ table, which is shown in ---(5)
Figure 7. # serialize the data
The ‘id’ field has been assigned as >>> serializer = class Student_post_get_view (APIView):
the primary key of the table by default. Studentserializer(student) def post(self,request):
You can set another field as the primary serializer=Studentserializer(da
key by including ‘primary_key=True’ # print serialized data ta=request.data)
as one of the parameters of the field >>> serializer.data if serializer.is_valid():
within the model definition in ‘models. ---(10)
py’. Now let’s jump into performing …the output of ‘serializer.data’ serializer.save()
CRUD operations for this model. would have been as follows: return Response(serializer.

68  |  MAY 2022  |  OPEN SOURCE FOR YOU  |  www.OpenSourceForU.com


How To Developers

‘getting_data’ variable. These objects


are then passed through the serializer
to be presented in JSON format as
per line (18). Just one step remains
before we can initiate inserting values
for our table. In ‘urls.py’ within
‘osfyproject1’, insert the following:

Figure 8: Sample of successful POST operation from django.contrib import admin


from django.urls import path
from firstapp.views import Student_post_
get_view

urlpatterns = [ ---(5)
path(‘admin/’, admin.site.urls),
path(‘student_post_get/’,Student_
post_get_view.as_view()),
Figure 9: Sample error messages ]

The URL path we entered in line (7)


helps us in carrying out the operations
present within ‘Student_post_get_
view’, i.e., the ‘POST’ and ‘GET’. In
the prompt, type:

python manage.py runserver

You should be able to see the link


http://127.0.0.1:8000/ in the output,
implying that the server is running.
We can now head to Insomnia to carry
out the ‘POST’ and ‘GET’ operations
(Figure 8)!
Figure 10: Displaying all information using GET Now let’s try botching these up to
see how validation errors are displayed.
data,status=status.HTTP_201_CREATED) data’ is a representation of the data As observed in Figure 9, we
return Response(serializer. we ‘POST’ in JSON format. ‘request. entered incorrect types of values
errors,status=status.HTTP_400_BAD_ data’ being assigned to the ‘data’ for ‘First_name’, ‘Student_ID’ and
REQUEST) parameter within the Studentserializer ‘Email_ID’ fields, but why is it that
implies that the entered data is passed we got error messages for only two
def get(self,request): to the serializer. Line (10) checks of them? This is because a serializer
---(15) the validation of the data entered takes the values that you enter for the
getting_data=Studentinfo. for the constituting fields within the fields and tries converting them to the
objects.all() model that the ‘Studentserializer’ field types you defined in the model,
serializer=Studentserializer(ge is associated with, i.e., Studentinfo. and checks for successful conversion.
tting_data,many=True) Line (12) displays the entered data Generally, in Python, a number of any
return Response(serializer. itself, indicating that there are no type — be it float, string, etc — can
data) validation errors, post the saving be converted to a string. Since it is
mentioned in line (11). Line (13) possible for the number 123 to be
The function ‘post’ corresponds helps return the errors (if any). As converted to string in Python, no error
to ‘Create’ operation, while the per line (16), all the objects present message is displayed for the same.
‘get’ function aligns with the ‘Read’ within the ‘Studentinfo’ model We will enter valid data for two more
operation. In line (9), the ‘request. (the existing data) are assigned to students and then perform the ‘GET’

www.OpenSourceForU.com  |  OPEN SOURCE FOR YOU  | MAY 2022  |  69


Developers How To

operation to see the information of all


three students (Figure 10).
Let’s move on to the ‘views.
py’ code for ‘PUT’ and ‘DELETE’
operations, which correspond to the
‘Update’ and ‘Delete’ operations in
CRUD:

class StudentDetails(APIView): Figure 11: GET-ting individual student info


def get_object(self,pk):
try:
return Studentinfo.objects.
get(pk=pk)
except Studentinfo.
DoesNotExist:
return
HttpResponse(status=status.HTTP_404_
NOT_FOUND) Figure 12: PUT-ting student info

def get(self,request,pk):
article=self.get_object(pk)
serializer=Studentserializer(a
rticle)
return Response(serializer.
data)

def put(self,request,pk):
article=self.get_object(pk)
serializer=Studentserializer(ar
ticle,data=request.data)
if serializer.is_valid(): Figure 13: Updated ‘GET’ output
serializer.save()
return Response(serializer. value. The ‘get’ function simply with pk=1. The change will be
data) displays the model entry with reflected when you ‘GET’ all
return Response(serializer. the given ‘pk’. ‘get’, ‘put’ and student info.
errors,status=status.HTTP_400_BAD_ ‘delete’ functions make use of the We will now delete the entry
REQUEST) ‘get_object’ function and treat it as in the model having pk=2. All
the first step in trying to obtain the you have to do is enter 2 in the
def delete(self,request,pk): required individual value. Add the URL as ‘http://127.0.0.1:8000/
article=self.get_object(pk) required URL in ‘urls.py’: student_details/2/’ and perform the
article.delete() ‘DELETE’ operation. Let’s see if the
return Response(status=status. path(“student_details/<int:pk>/”,Stud same is reflected in the model.
HTTP_204_NO_CONTENT) entDetails.as_view(), Having gone through the article,
), you would have grasped an idea of
The ‘get_object’ function aims to the absolute basics of generating
obtain the object within the existing In Figure 12, I aimed to change APIs; specifically, how to perform
table having the same primary key just the ‘Last_name’ of the student CRUD operations.
value, i.e., ‘pk’ as the one entered
in the URL. It will return an error By: Mohammed Kamil Khan
message if no entry in our model
The author is currently working at Vamstar as a data discovery expert.
exists with the entered primary key

70  |  MAY 2022  |  OPEN SOURCE FOR YOU  |  www.OpenSourceForU.com

You might also like