flask-restful
flask-restful

There are three major types of API frameworks as discussed in one of out previous posts and REST is one of them. Representational State Transfer (REST) is a  software architectural style that defines a set of constraints to be used for creating web services. RESTful web services, provide interoperability between computer systems on the Internet.

What we will create

We are going to develop restful API endpoints for a blog app. The should allow one to create a blog post, get all blogs, get a single blog and delete a single blog. We will be using data structures to store our data

In our next blog, we will be writing tests for our blog app and I’ll advice you subscribe to our mailing list and recheck our blog for more useful tutorials.

Creating virtual environment

The first step any application is creating its own directory. So go ahead in your root directory, create folder called myblog and initialize your virtual environment inside the folder.

$ mkdir myblog 
$ cd myblog 
$ virtualenv venv 
New python executable in venv/bin/python Installing setuptools, pip............done. 

Activate the virtual environment and export some variables in the environment.

$ source env/bin/activate
(env) $ export FLASK_APP=run.py
(env) $ export FLASK_DEBUG=1
(env) $ export FLASK_ENV=development

Folder structure

We are not currently going to implement python folder structure into this tutorial and the moment our working directory structure will be as simple as this.

├── myblog (this is the directory we cd into)
    ├── run.py 
    ├── requirements.txt
    ├── views.py
    └── test_myblog.py

Installing dependencies

We are majorly going to install and use two major flask libraries

(env) $ pip install flask
(env) $ pip install flask-restful
(env) $ pip freeze > requirements.txt

Create app

Add the following code to run.py

from flask import Flask

app = Flask(__name__)

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

In the file above , we are just creating a flask app and running the app. Its that simple. More description on the lines of code, checkout – Getting started with flask – Python

Run the app

(env) $ flask run
 * Serving Flask app "run.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 216-498-286

Add the following lines of code to views.py

from flask_restful import Resource

blog_list = []
class Blogs(Resource):
    """docstring for Blogs"""
    def post(self):
        """creating a blog"""
        pass

    def get(self):
        """retrieving all blogs"""
        pass


class SingleBlog(Resource):
    """docstring for SingleBlog"""
    def get(self, id):
        """retrieving a single blog based on id"""
        pass

    def delete(self, id):
        """deleting a single blog based on id"""
        pass

    def put(self, id):
        """editing a single blog based on id"""
        pass

The flask restful work is that it takes care of all the endpoints as resources and thats why we import Resource  into our Blog and SingleBlog classes.

Also note, instead of providing the method types as discussed here when building a APIs using pure flaks, flask RESTful uses method names as the request type. Please note that methods in the same class will and can share urls/route. However, there cannot be more than one similar methods in one class and that why we came up with SingleBlog class to handle the next get for getting single blogs.

Adding Resources/Endpoints to our app

Add the following lines of code to the specified classes:

The post Method inside the Blog class is used to create a new user

    def post(self):
        """creating a blog"""
        req = request.get_json()
        new = {
            "id": len(blog_list) + 1,
            "tittle": req['tittle'],
            "description": req['description'],
            "date": datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
        }
        blog_list.append(new)
        return make_response(jsonify({
            "msg": "Created",
            "blog_id": new['id']
        }), 201)

We will create a request body by using request we imported earlier, add the tittle and description keys to the request, then store the request body in a variable, req (the arguments will come from request body in the form of form-data, JSON or XML).

The get Method inside the Blog class is used to retrieve all users :

    def get(self):
        """retrieving all blogs"""
        return make_response(jsonify({
            "msg": "ok",
            "blogs": blog_list
        }), 200)

The get Method inside the SingleBlog class is used to retrieve a particular blog by specifying the id:

def get(self, id):
        """retrieving a single blog based on id"""
        for blog in blog_list:
            if blog['id'] == id:
                return make_response(jsonify({
                    "msg": "ok",
                    "blog": blog
                }), 200)

            return make_response(jsonify({
                "msg": "Not found"
            }), 404)

We will traverse through our blog list to search for the blog, if the id specified matched with one of the blog in blog list, we will return the user, along with 200 OK, else return a user not found message with 404 Not Found. Another characteristic of a well designed REST API is that it uses standard HTTP response status codeto indicate whether a request is being processed successfully or not

The delete Method inside the SingleBlog class is used to delete a particular blog by specifying the id:

def delete(self, id):
        """deleting a single blog based on id"""
        global blog_list
        blog_list = [blog for blog in blog_list if blog['id'] != id]
        return make_response(jsonify({
            "msg": "Blog with id {} id deleted".format(id)
        }), 200)

By specifying blog list as a variable in global scope, we update the blog list using list comprehension to create a list without the id specified (simulating delete), then return a message along with 200 OK.

The put Method inside the SingleBlog class is used to update a particular blog by specifying the id:

def put(self, id):
        """editing a single blog based on id"""
        for blog in blog_list:
            if blog['id'] == id:
                req = request.get_json()
                blog['tittle'] = req['tittle']
                blog['description'] = req['description']
                blog['updated'] = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
                return make_response(jsonify({
                    "msg": "ok",
                    "blog": blog
                }), 200)

            updated_blog = {
                "id": id,
                "tittle": req['tittle'],
                "description": req['description'],
                "updated": datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')
            }
            blog_list.append(updated_blog)

            return make_response(jsonify({
                "msg": "ok",
                "blog": blog
            }), 201)

If the blog already exist, we will update its details with the request.get_json() and return the user along with 200 OK, else we will create and return the user along with 201 Created.

Linking the resources to the app

Add the following lines to run.py

from flask import Flask
from flask_restful import Api
from views import Blogs, SingleBlog

app = Flask(__name__)
api = Api(app)

api.add_resource(Blogs, '/blog')
api.add_resource(SingleBlog, '/blog/<int:id>')


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

Note: 
<int:id> indicates that it is a variable part in the route which accepts any id. 

Testing

Save the changes in your files above and since flask was running in debug mode, you really don’t need to restart it.

The full code is also available on GitHub

I recommend using insomnia or Postman or Curl to test your application

testing-flask-restful
testing-flask-restful

Conclusion

Thanks for reading this article, hopefully by now you have an idea on how to write a RESTful API rapidly using Flask, as well as adhere to some existing standards to design a high quality RESTful API.

If you think this tutorial was helpful, please tap the thumbs up button and share with your friends to show your support! Your encouragement will definitely be my motivation to write more article or tutorial like this. In the next part, we will be writing tests for this code the TDD way.

4 COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here