RESTful Web Services with Python Flask


The idea of this post is to describe how to develop a RESTful Web Services in Python.

RESTful Web Service is an architectural style, where the data or the structural components of a system is described  in the form of URI ( Uniform Resource Identifier) and the behaviors are described in-terms of methods.  The resources can be manipulated using CRUD (Create, Read, Update and Delete) operations.   The communication protocol for REST is HTTP, since it suits the architecture requirement of being a stateless communication across the Client and Server.

There are many frameworks available in Python for web development, but Django  (pronounced as yango ) and Flask stands out of the crowd being a full stack frameworks.  I prefer Flask framework, since it is very small and easy to learn for beginners, where as Django is too big for beginners.

1. The Plan

In this exercise we will create a in memory JSON DB to store and manipulate a simple employee database and develop RESTful APIs to perform CRUD operations using GET, POST, PUT & DELETE methods.

We will develop the below APIs

i) GET  /empdb/employee/                      – Retrieve all the employees from the DB

ii) GET /empdb/employee/       – Retrieve the details of given employee Id

ii) POST /empdb/employee/                       – Create a record in the employee DB, where as the employee details are sent in the request as a JSON object

III) PUT /empdb/employee/                    – Update the employee DB, with the given details of employee in the data part as a JSON object

Iv) DELETE /empdb/employee/ – Delete the employee from the DB for the employee Id.

2. Installation of flask

To install flask framework, please refer the official website [1]  . If you have pip installed in your Python environment, please follow this step.

$ pip install Flask

If you don’t have pip, please download the flask from http://pypi.python.org/packages/source/F/Flask/Flask-0.10.1.tar.gz and execute the setup.py .

3. Hello World – Web Server

First we create a web server, create a dictionary to hold a JSON objects for couple of employee records and then we add RESTful APIs for each supported operations.

Please look at the below program, which create a web server.  Save the below program into hello.py and execute it.

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

The below line from the code creates an app object from Flask.

app = Flask(__name__)

app.run() starts the web server and ready to handle request.  But at this moment it can handle only one request.  It is defined in the below line of code.

@app.route("/")
def hello():
    return "Hello World !"

Execute the above program & you will see that you web server is ready to service you.

* Running on http://localhost:5000/

Now you can open your web browser and check your web server.  The server is available in the URL http://localhost:5000/.  If you are familier with cUrl execute the below to check the status.

$ curl -i http://localhost:5000/

4. Develop the RESTful Services

To develop the restful services for the planned objective, lets create a in memory database in python using the dictionary data type.  Please find the code snippet below:  We can continue to use the hello.py and type the below code, just after the Flask app creation statement app = Flask(__name__).  You can also refer the below section 5 for the complete code.

empDB=[
 {
 'id':'101',
 'name':'Saravanan S',
 'title':'Technical Leader'
 },
 {
 'id':'201',
 'name':'Rajkumar P',
 'title':'Sr Software Engineer'
 }
 ]

4.1 GET

In the previous section, we have created two employees in the dictionary.  Now lets write a code to retrieve them using web services.  As per our plan, we need two implementations one is to retrieve all the employees and another one to retrieve the specific employee with the given id.

4.1.1 GET All
@app.route('/empdb/employee',methods=['GET'])
def getAllEmp():
    return jsonify({'emps':empDB})

In the above code snippet, we have created a URI named ‘/empdb/employee’ and also we defined the method as “GET”.  To service the GET call for the URI,  Flask will call the function getAllEmp().  It will inturn simply calls the “jsonify” method with employeeDB as the argument.  The “jsonify” is a flask method, will set the data with the given JSON object which is passed as a Python dictionary and set the headers appropriately, in  this case “Content-type: application/json”.

We can check the above Web Service with cUrl as below:

cUrl> curl -i http://localhost:5000/empdb/employee
Response for CURL

Response for CURL

4.1.2 Get Specific

Now we develop the rest service to get a employee with a given id.

@app.route('/empdb/employee/<empId>',methods=['GET'])
def getEmp(empId):
    usr = [ emp for emp in empDB if (emp['id'] == empId) ] 
    return jsonify({'emp':usr})

The above code will find the employee object with the given id and send the JSON object in the data.  Here I have used the list comprehension technique in Python, if you don’t understand you can simply write in a imperative way of processing the entire dictionary using a for loop.

CURL > curl -i http://localhost:5000/empdb/employee/101

The response would be :

Get An Employee

4.2 PUT

PUT method is used to update the existing resource.  The below code gets the employee id from the URL and finds the respective object.  It checks the request.json from the request for the new data & then it over writes the existing.

NOTE : the request.json will contain the JSON object set in the client request.

@app.route('/empdb/employee/<empId>',methods=['PUT'])
def updateEmp(empId): 
    em = [ emp for emp in empDB if (emp['id'] == empId) ] 
    if 'name' in request.json : 
        em[0]['name'] = request.json['name'] 
    if 'title' in request.json:
        em[0]['title'] = request.json['title'] 
 return jsonify({'emp':em[0]})

We can also use a Postman client or cUrl to update an existing employee.  The data must contain the JSON object either with a name or title.

The service can be invoked as follows in cUrl.  Here we update the “title” for employee id 201 with “Technical Leader”. The request is responded with employee json object with updated values.  It also updates the employee DB.

03-Post

4.3 POST

POST method is used to create a new employee inside the data base.  The code snippet is below:

@app.route('/empdb/employee',methods=['POST'])
def createEmp(): 
    dat = {
    'id':request.json['id'],
    'name':request.json['name'],
    'title':request.json['title']
    }
 empDB.append(dat)
 return jsonify(dat)

The above code, simply reads the request.json for the expected values, and stores them in the local dictionary object and appends it to the employee DB dictionary.  This also returns the newly added employee object as the response.

4.4 DELETE

Lets write a code to delete a given employee id.

@app.route('/empdb/employee/<empId>',methods=['DELETE'])
def deleteEmp(empId): 
    em = [ emp for emp in empDB if (emp['id'] == empId) ] 
    if len(em) == 0:
    abort(404) 
    
    empDB.remove(em[0])
    return jsonify({'response':'Success'})

the above service can be used as follows:

05-delete

5 Complete Code

from flask import Flask
from flask import jsonify
from flask import request

app = Flask(__name__)

empDB=[
 {
 'id':'101',
 'name':'Saravanan S',
 'title':'Technical Leader'
 },
 {
 'id':'201',
 'name':'Rajkumar P',
 'title':'Sr Software Engineer'
 }
 ]

@app.route('/empdb/employee',methods=['GET'])
def getAllEmp():
    return jsonify({'emps':empDB})

@app.route('/empdb/employee/<empId>',methods=['GET'])
def getEmp(empId):
    usr = [ emp for emp in empDB if (emp['id'] == empId) ] 
    return jsonify({'emp':usr})


@app.route('/empdb/employee/<empId>',methods=['PUT'])
def updateEmp(empId):

    em = [ emp for emp in empDB if (emp['id'] == empId) ]

    if 'name' in request.json : 
        em[0]['name'] = request.json['name']
 
    if 'title' in request.json:
        em[0]['title'] = request.json['title']
 
    return jsonify({'emp':em[0]})
 

@app.route('/empdb/employee',methods=['POST'])
def createEmp():

    dat = {
    'id':request.json['id'],
    'name':request.json['name'],
    'title':request.json['title']
    }
    empDB.append(dat)
    return jsonify(dat)

@app.route('/empdb/employee/<empId>',methods=['DELETE'])
def deleteEmp(empId):
    em = [ emp for emp in empDB if (emp['id'] == empId) ]
 
    if len(em) == 0:
       abort(404)
 
    empDB.remove(em[0])
    return jsonify({'response':'Success'})

if __name__ == '__main__':
 app.run()

6 CONCLUSION

This is a very basic web services we have developed.  I hope this helps to understand basics of RESTful Web Services development.  We can make this implementation clean by proper error handling and authentication.   I suggest to everyone to visit the official documentation of Flask for further learning.

Reference

[1] Flask – http://flask.pocoo.org/

Leave a comment