Flask Python Tutorial

Building Simple RESTful API with Flask

Posted on

RESTful API is very popular trends right now. Almost web application use API to provide a client-server application. Today we are gonna learn REST API example by building a simple RESTful API with Flask. Flask is a framework based on Python. It is very powerful and lightweight to build any web application.

What is REST

The full name of REST is REpresentational State Transfer, it is an architectural style to expose database securely to the client with six guidelines. The web architecture that satisfies the following six criteria can be said to be RESTful.

  1. Client-Server. There is a clear line between the server and the client. On the server side no longer pays attention to the user interface and user status. On the other hand, the client is no longer concerned about the storage of data. In this way, the server and the client can be developed independently, as long as they comply with the convention.
  2. Stateless. Each request from the client must contain all the information the server needs. That is, the server does not store information about a request from the client, which should be maintained by the client.
  3. Cache-able. The returned content can be cached somewhere in the communication chain to reduce the number of interactions and improve network efficiency.
  4. Layered System. Allows the server to communicate with the client by introducing a middle tier (such as a proxy, gateway, etc.) instead of the server, and these do not require special support for the client.
  5. Uniform Interface. Client and server communicate with each other through a unified interface (such as GET, POST, PUT, DELETE, etc.).
  6. Support on-demand code (Code-On-Demand, optional). The server can provide some code (such as Java) and execute it in the client to extend some of the client’s functionality.

Design

The core concept of REST web services is resources. The resource is located by the URI (Uniform Resource Identifier), and the client uses the HTTP protocol to access these resources. We summarize it with a sentence which is not very comprehensive: URI locates the resource, uses HTTP request method (GET, POST, PUT, DELETE) to get response from server.

We will build simple CRUD (Create, Read, Update, Delete) function, allowing us to create, retrieve, modify, and delete users.

What we need to prepare first

We will build our app inside docker container. Without docker, we will face many complicated issues in development environment. Each programmer will have different environment setup. Application will run at programmer A’s environment, but maybe not at programmer B’s. And maybe will not run when deploy to production server. Docker simplify that problems using virtual machine Linux via VirtualBox.

  • Docker
  • Docker-Compose

Environment that we will build:

  • Python 2.7-alpine
  • Flask
  • Flask-Restful

Let’s Begin to Code

Use your favorite IDE. I use PyCharm.

Make new project and define virtualenv using Python 3.7.

At root project create Dockerfile

FROM python:2.7-alpineMAINTAINER WahyuENV INSTALL_PATH /web_appRUN mkdir -p $INSTALL_PATHWORKDIR $INSTALL_PATH#copy requirements.txt to workdir at containerCOPY requirements.txt requirements.txtRUN pip install -r requirements.txt

Create requirements.txt to list what module we will use.

flaskflask-restfulgunicorn

Now, create app.py inside web_app module and edit it using your favorite editor.

First import the module and set up the Flask-Restful application:

from flask import Flaskfrom flask_restful import Api, Resource, reqparseapp = Flask(__name__)api = Api(app)

Next, we create a data list and a dictionary to simulate the data store:

users = [    {        "username": "Agung",        "age": 24,        "occupation": "Network Engineer"    },    {        "username": "Huda",        "age": 32,        "occupation": "Doctor"    },    {        "username": "Sony",        "age": 42,        "occupation": "Web Engineer"    }]

Now we define a User resource class to start creating our API nodes:

class User(Resource):    def get(self, name):        pass    def post(self, name):        pass    def put(self, name):        pass    def delete(self, name):        pass

One of the high quality of the REST API is that it follows standard HTTP methods to indicate the intended action to perform.

Refine the get method:

class User(Resource):    def get(self, name):        for user in users:            if name == user["username"]:                return user, 200        return "User not found", 404

We will traverse our user list to search for users. If the specified name matches one of the users in the user list, we will return the user and return 200 OK . Otherwise , the user who cannot be found, we will return a message and 404 return code. Another feature of the well-designed REST API is that it uses a standard HTTP response status code to indicate whether the request is successfully processed.

Create user:

    def post(self, name):        parser = reqparse.RequestParser()        parser.add_argument("age")        parser.add_argument("occupation")        args = parser.parse_args()        for user in users:            if name == user["username"]:                return "User with name {} alreadly exists.".format(name), 400        user = {            "username": name,            "age": args["age"],            "occupation": args["occupation"]        }        users.append(user)        return user, 201

We will use the previously imported reqparse to create a parser, add the age and occupation parameters to the parser, and store the parsed parameters in a variable, args (the parameters will be in form-data, JSON or XML). If the user with the same name already exists, the API will return a message and 400 error requests, otherwise we will create the user by appending the user to the user list and return the user and 201 return code.

Modify user:

    def put(self, name):        parser = reqparse.RequestParser()        parser.add_argument("age")        parser.add_argument("occupation")        args = parser.parse_args()        for user in users:            if name == user["username"]:                user["age"] = args["age"]                user["occupation"] = args["occupation"]                return user, 200        user = {            "name": name,            "age": args["age"],            "occupation": args["occupation"]        }        users.append(user)        return user, 201

delete users:

    def delete(self, name):        global users        users = [user for user in users if user["username"] != name]        return "{} is deleted.".format(name), 200

Finally, add resources to the route and run the Flask app.

api.add_resource(User, "/user/<string:name>")

Now, we need to create a docker-compose.yml file:

version: '3'services:  web_app:    container_name: simple-rest    build: .    command: >      gunicorn -b 0.0.0.0:8000      --access-logfile -      --reload      "web_app.app:create_app()"#in production remove --reload option    environment:      PYTHONUNBUFFERED: 'true'    volumes:      - '.:/web_app'    ports:      - '7000:8000'

We will expose port 8000 from container server from gunicorn to port 7000 in host. Since gunicorn call create_app() function, we need to modify our app.py, and put our code inside def create_app(): function, and put return app in the last line of the function.

To run our app, type this docker compose command:

docker-compose up -d --build

This command will run docker-compose.yml and then detach back to command line --build option will rebuild the code if any changes to our source.

Now we can test it in your browser to : http://localhost:7000

And try to access our user, i.e. http://localhost:7000/user/Agung and you will see a JSON format for user Agung

You are done! Easy isn’t it?

Leave a Reply

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