Srikanth Technologies

REST API in Django + jQuery Client

In this blog, I will create a Restful Service also known as REST API using Django REST Framework and then access it from HTML page that uses jQuery Library.

Install Django

First step is to install Django Framework using PIP as follows:

pip install django

Make sure you are in Scripts folder of Python installation directory to access PIP. Alternatively include Scripts folder in system PATH.

Install Django Rest Framework

Django REST framework is used to build REST API. It is based on Django Framework, which we installed in previous step. Use PIP as follows to install Django REST Framework.

pip install djangorestframework

Create Project and Application

Create a new project and an application by following steps given below.

Go to directory (like c:\dev\python) where you want to place project and give the following commands. Program django-admin.exe is placed in Scripts folder when you install Django framework.

django-admin startproject courses
When we create a new project, Django creates a folder with manage.py and another folder within it with same name as project (courses).

Let's move into courses folder (where manage.py is placed) and then execute the following command to create a new application called RestAPI.

python manage.py startapp restapi

Now, start PyCharm IDE and select File -> Open option. Select courses folder (that was created by startproject command) so that it is opened as a project in PyCharm IDE.

The following image shows the directory structure of courses project as of now.

Modify Settings.py

We need to add our application and Django REST Framework to INSTALLED_APPS list in settings.py of courses folder as shown below:

INSTALLED_APPS = [
    'restapi',  # Our Application
    'rest_framework',   # Django REST Framework  
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Create Model - Course

We store details of courses in Courses table in SQLite database. We use Django ORM to manipulate data in Courses table. Let's create a model that represents row (course) in courses table.

A model is a class that is a subclass of Model class and placed in Models.py, which is in restapi folder.

from django.db import models

class Course(models.Model):
    code = models.CharField(max_length=5, null=False, primary_key=True)
    title = models.CharField(max_length=30, null=False, unique=True)
    duration = models.IntegerField(null=False)
    fee = models.IntegerField(null=False)

    def __str__(self):
        return self.title

    class Meta:
        db_table = "Courses"

Migrate Model To Database

Let's create a table for class Course in SQLite database. By default, Django creates tables for models (classes derived from Model) in db.sqlite3 file in courses/courses folder. This file based database is automatically created at the time of migration.

By default it creates a table with name applicationname_modelname, but we override that name by using db_table attribute of Meta class in Course class as shown in code above.

We need to give the following commands from Courses folder to migrate Model to database.

 

python manage.py makemigrations
The above command creates required scripts for migration and places them in migrations folder inside restapi folder.

python manage.py migrate
The above command uses scripts created by makemigrations command and creates required database objects.

Create Serializer - CourseSerializer

Serializer is meant to convert model attributes to JSON and JSON to model attributes. Conversion from model to JSON is called serialization and conversion from JSON to model is called deserialization.

Serializer CourseSerializer is used to serialize and deserialize Course model. We need to specify model to serialize and attribute to include using Meta class. We place CourseSerializer in views.py along with other function views to keep all in one module. However, serializers are generally placed in a separate module called serializers.py.

Create REST API

REST API is an endpoint (URL) that supports different HTTP methods. Our REST API supports GET,POST,PUT and DELETE.

Method GET, PUT and DELETE are expected to take course code along with URL. Ex: /rest_courses/py,  where py is course code.

When method GET is called without any course code, it returns all courses, otherwise it returns details of course whose code is provided.

Method POST takes details of new course as request parameters and inserts a new row in Courses table.

Method PUT takes course code along with URL and data  to update existing course as request parameters.

Method DELETE takes course code along with URL and deletes course with that code.

We need to provide function views to handle client request as follows in views.py of restapi application.

from rest_framework import serializer
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Course
from django.shortcuts import render
    
class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = ('code', 'title', 'duration', 'fee')


def client(request):
    return render(request,"rest_client.html")


@api_view(['GET','POST'])
def list_courses(request):
    if request.method == "GET":
       courses = Course.objects.all()
       serializer = CourseSerializer(courses, many=True)
       return Response(serializer.data)
    else:  # Post
        serializer = CourseSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)  # Successful post

        return Response(serializer.errors, status=400)  #Invalid data



@api_view(['GET','DELETE','PUT'])
def course_details(request, code):
    try:
        course = Course.objects.get(code=code)
    except:
        return Response(status=404)

    if request.method == 'GET':
        serializer = CourseSerializer(course)
        return Response(serializer.data)
    elif request.method == 'PUT':    # Update
        serializer = CourseSerializer(course, data=request.data)
        if serializer.is_valid():
           serializer.save()    # Update table in DB
           return Response(serializer.data)

        return Response(serializer.errors, status=400)  # Bad request
    elif request.method == 'DELETE':
        course.delete()
        return Response(status=204)

Add URLS

Last step in the creation of REST API is to include URLs related to it in urls.py of courses folder as follows:

from django.contrib import admin
from django.urls import path, re_path
from restapi import views

urlpatterns = [
    path('rest_courses/',  views.list_courses),
    re_path('rest_courses/(?P<code>\w+)/$', views.course_details),
    path('rest_client/', views.client),
]

Testing REST API

Let's start server and test REST API before we create jQuery client.

Start django server as follows from courses folder that contains manage.py module.

python manage.py runserver

Once server is up and running, we can test our REST API by giving the following URLs in browser as shown below. Django REST Framework provides interface to test your API. It is possible to make GET, POST, DELETE and PUT requests using client provided by Django REST Framework. As our goal is to use jQuery to create a client, I don't discuss about how to use the client provided by REST Framework.

Create jQuery Client

In order to create HTML page that contains jQuery client to make AJAX requests to REST API, we need to create templates folder in restapi folder and place the following template (HTML page). This template is rendered when /rest_client url is requested.

<html>
<head>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script>
    var URL = "/rest_courses/";

    $(document).ready(
       function() {
          $("#courses").hide();
       }
    );

    function getCourses()
    {
       $.getJSON(URL,{},showCourses);
    }

    function getCourse()
    {
       $.getJSON(URL + $("#code").val())
           .done(showCourse)   // on success - 200
           .fail(function()    // on failure - 404
                 {
                      alert("Sorry! Course Not Found!");
                 }
           );
    }

    function showCourse(course)
    {
        $("#title").val(course.title)
        $("#duration").val(course.duration)
        $("#fee").val(course.fee)
    }

    function showCourses(courses) {
       $("#courserows").html("")
       $.each(courses,
              function(idx,course) {
                 $("#courserows").append("<tr><td>" + course.code + "</td><td>" +
                       course.title + "</td><td>" + course.duration + "</td><td>" +
                       course.fee + "</td></tr>");
              } // anonymous function
        ); // each()

        $("#courses").show();
   } // showCourses

    function addCourse()
    {
       $.ajax(
          { "url": URL,
             "data": {
                       "code" : $("#code").val(),
                       "title" : $("#title").val(),
                       "duration" : $("#duration").val(),
                       "fee" : $("#fee").val()
                     },
             "type" : "post",
             "success" : add_success,
             "error" : add_error
          }
      ); // ajax()
    }

    function add_success()
    {
      alert("Added course Successfully");
    }

    function add_error()
    {
      alert("Could not add course!");
    }

    function deleteCourse()
    {
       $.ajax(
          {  "url": URL + $("#code").val(),
             "type" : "delete",
             "success" : delete_success,
             "error" : delete_error
          }
      ); // ajax()
    }

    function delete_success()
    {
      alert("Deleted Course Successfully");
    }

    function delete_error()
    {
      alert("Could not delete Course!");
    }


    function updateCourse()
    {
       $.ajax(
          {  "url"     : URL + $("#code").val() + "/",
             "data"    : { "code"     : $("#code").val(),
                           "title"    : $("#title").val(),
                           "duration" : $("#duration").val(),
                           "fee"      : $("#fee").val()
                          },
             "type"    : "put",
             "success" : update_success,
             "error"   : update_error
          }
      ); // ajax()
    }

    function update_success()
    {
      alert("Updated Course Successfully");
    }

    function update_error()
    {
      alert("Could not update Course!");
    }
    </script>
</head>
<body>
<div style="background-color:navy;color:white;font-family:arial;font-size:20pt;font-weight:bold">Course Client</div>
<p/>
Code <br/>
<input type="text" id="code"/>
<br/>
Title <br/>
<input type="text" id="title"/>
<br/>
Duration <br/>
<input type="number" id="duration"/>
<br/>
Fee <br/>
<input type="number" id="fee"/>
<p/>
<button onclick="getCourse()">Details</button>
<button onclick="addCourse()">Add </button>
<button onclick="deleteCourse()">Delete </button>
<button onclick="updateCourse()">Update </button>
<button onclick="getCourses()">List</button>
<p/>

<table border="1" cellpadding="5pt" id="courses">
    <thead>
    <tr>
        <th>Code</th>
        <th>Title</th>
        <th>Duration</th>
        <th>Fee</th>
    </tr>
    </thead>
    <tbody id="courserows"></tbody>
</table>
</body>
</html>

The above template is simple HTML page to make different types of requests (like GET, POST etc.) to REST API using jQuery methods.

Use the button in this page to test various operations supported by our REST API.

The following page shows list of courses when List button is selected. Of course I added a few courses before that as Courses table was empty at the beginning.

Run client as shown in the screenshot (http://localhost:8000/rest_client/) and test all operations.

Post Your Comment

Image
Enter the code given in the above image :
Enter Your Name :
Enter Your Email Address :
Enter Your Comment :

Comments