1. Code
  2. Coding Fundamentals
  3. Rest API

Building RESTful APIs With Flask: The DIY Approach

Scroll to top
This post is part of a series called Building RESTful APIs With Flask.
Building RESTful APIs With Flask: An ORM With SQLAlchemy

REST (REpresentational State Transfer) is a web development architecture design style that refers to logically separating your API resources to enable easy access, manipulation, and scaling. Reusable components are written to be easily managed via simple and intuitive HTTP requests such as GET, POST, PUT, PATCH, and DELETE (there can be more, but these are the most commonly used ones).

Despite what it looks like, REST does not command a protocol or a standard. It just sets a software architectural style for writing web applications and APIs and simplifies the interfaces within and outside the application. Web service APIs that are written to follow the REST principles are called RESTful APIs.

In this three-part tutorial series, I will cover how RESTful APIs can be created using Flask as a web framework. The first part will cover how to create class-based REST APIs in a DIY way (do it yourself)—implementing them all by yourself without using any third-party extensions. In the latter parts of this series, I will cover how to leverage various Flask extensions to build more effective REST APIs more easily.

Getting Started

Let's start by creating a project directory and a virtual environment.

1
mkdir flask_app
2
cd flask_app
3
python3.8 -m venv env

4
source env/bin/activate

Installing Dependencies

The following packages need to be installed for the application that we'll be developing.

1
$ pip install flask
2
$ pip install -U Flask-SQLAlchemy

The above commands should install all the required packages that are needed for this application to work.

The Flask Application

For this tutorial, we will create a small application to create a trivial model for a product, and then I'll demonstrate how we can write a RESTful API for it. Below is the structure of the application.

1
flask_app/
2
    my_app/
3
        - __init__.py
4
        product/
5
            - __init__.py      // Empty file
6
            - models.py
7
            - views.py
8
    - run.py

We won't be creating a front-end for this application as RESTful API endpoints can be tested directly by making HTTP calls using various other methods. Open my_app/__int__.py and add the following code.

1
# flask_app/my_app/__init__.py

2
3
from flask import Flask
4
from flask_sqlalchemy import SQLAlchemy
5
6
app = Flask(__name__)
7
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mydb.db'
8
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
9
db = SQLAlchemy(app)
10
11
db.create_all()

We first initialize a Flask app instance in the code above, configure it with an SQLite database, and finally create the database. db.create_all() will create a new database at the location provided against SQLALCHEMY_DATABASE_URI if a database does not already exist at that location; otherwise, it loads the application with the same database.

Open product/models.py and add the models for our product. The model will have three fields:

  • id: a unique primary key
  • name
  • price
1
from my_app import db
2
3
class Product(db.Model):
4
    id = db.Column(db.Integer, primary_key=True)
5
    name = db.Column(db.String(255))
6
    price = db.Column(db.Float(asdecimal=True))
7
8
    def __init__(self, name, price):
9
        self.name = name
10
        self.price = price
11
12
    def __repr__(self):
13
        return '<Product %d>' % self.id
14

In the file above, we have created a very trivial model for storing the name and price of a Product. This will create a table in SQLite corresponding to the details provided in the model.

Flask Blueprint

Flask blueprints help to create structure in a Flask application by grouping views, templates, etc. into reusable components. Open product/views.py and create a Flask blueprint that contains the home view, and then use it in the application.

1
from flask import Blueprint, abort
2
from my_app import db, app
3
from my_app.product.models import Product
4
5
catalog = Blueprint('catalog', __name__)
6
7
@catalog.route('/')
8
@catalog.route('/home')
9
def home():
10
    return "Welcome to the Catalog Home.

To use the blueprint, you have to register it in the application using the register_blueprint() command. Open my_app/__init__.py and add:

1
from my_app.product.views import catalog
2
app.register_blueprint(catalog)

Views

Open product.views.py and create our views. We will use pluggable class-based views, which provide flexibility. 

1
import json
2
from flask import request, jsonify, Blueprint, abort
3
from flask.views import MethodView
4
from my_app import db, app
5
from my_app.catalog.models import Product
6
7
catalog = Blueprint('catalog', __name__)
8
9
@catalog.route('/')
10
@catalog.route('/home')
11
def home():
12
    return "Welcome to the Catalog Home."
13
14
15
class ProductView(MethodView):
16
17
    def get(self, id=None, page=1):
18
        if not id:
19
            products = Product.query.paginate(page, 10).items
20
            res = {}
21
            for product in products:
22
                res[product.id] = {
23
                    'name': product.name,
24
                    'price': str(product.price),
25
                }
26
        else:
27
            product = Product.query.filter_by(id=id).first()
28
            if not product:
29
                abort(404)
30
            res = {
31
                'name': product.name,
32
                'price': str(product.price),
33
            }
34
        return jsonify(res)
35
36
    def post(self):
37
        name = request.form.get('name')
38
        price = request.form.get('price')
39
        product = Product(name, price)
40
        db.session.add(product)
41
        db.session.commit()
42
        return jsonify({product.id: {
43
            'name': product.name,
44
            'price': str(product.price),
45
        }})
46
47
    def put(self, id):
48
        # Update the record for the provided id

49
        # with the details provided.

50
        return
51
52
    def delete(self, id):
53
        # Delete the record for the provided id.

54
        return

The major crux of this tutorial is dealt with in the file above. Flask provides a utility called pluggable views, which allows you to create views in the form of classes instead of normally as functions. Method-based dispatching (MethodView) is an implementation of pluggable views which allows you to write methods corresponding to the HTTP methods in lower case. In the example above, I have written the get() and post() methods corresponding to HTTP's GET and POST respectively.

Here we create a ProductView class that defines a get and post function. The get function retrieves the products from the database and paginates the results. 

The post method obtains request data in JSON format and adds the data to the database.

Routing

Routing is also implemented in a different manner. After adding the views, add the routes.

1
product_view =  ProductView.as_view('product_view')
2
app.add_url_rule(
3
    '/product/', view_func=product_view, methods=['GET', 'POST']
4
)
5
app.add_url_rule(
6
    '/product/<int:id>', view_func=product_view, methods=['GET']
7
)

In the code above, we can specify the methods that will be supported by any particular rule. Any other HTTP call would be met by Error 405 Method not allowed.

Running the Application

To run the application, execute the script run.py. The contents of this script are:

1
from my_app import app
2
app.run(debug=True)

Now, just execute from the command line:

1
$ python run.py

To check if the application works, fire up http://127.0.0.1:5000/ in your browser, and a simple screen with a welcome message should greet you.

Testing the RESTful API

To test this API, we can simply make HTTP calls using any of the many available methods. GET calls can be made directly via the browser. POST calls can be made using a Chrome extension like Postman or from the command line using curl, or we can use Python's requests library to do the job for us. I'll use the requests library here for demonstration purposes. Start by installing the requests library using pip:

1
pip install requests

Let's make a GET call first to ensure that we don't have any products created yet. As per the RESTful API design, a get call which looks something like /product/ should list all products. Then I will create a couple of products by making POST calls to /product/ with some data. Then a GET call to /product/ should list all the products created. To fetch a specific product, a GET call to /product/<product id> should do the job.

Enter the Python interactive shell:

1
python3.8

 Below is a sample of all the calls that can be made using this example.

1
>>> import requests
2
>>> r = requests.get('http://localhost:5000/product/')
3
>>> r.json()
4
{}
5
>>> r = requests.post('http://localhost:5000/product/', data={'name': 'iPhone 6s', 'price': 699})
6
>>> r.json()
7
{u'1': {u'price': u'699.0000000000', u'name': u'iPhone 6s'}}
8
>>> r = requests.post('http://localhost:5000/product/', data={'name': 'iPad Pro', 'price': 999})
9
>>> r.json()
10
{u'2': {u'price': u'999.0000000000', u'name': u'iPad Pro'}}
11
>>> r = requests.get('http://localhost:5000/product/')
12
>>> r.json()
13
{u'1': {u'price': u'699.0000000000', u'name': u'iPhone 6s'}, u'2': {u'price': u'999.0000000000', u'name': u'iPad Pro'}}
14
>>> r = requests.get('http://localhost:5000/product/1')
15
>>> r.json()
16
{u'price': u'699.0000000000', u'name': u'iPhone 6s'}
17

Conclusion

In this tutorial, you saw how to create RESTful interfaces all by yourself using Flask's pluggable views utility. This is the most flexible approach while writing REST APIs but involves writing much more code. 

There are extensions that simplify life and automate the implementation of RESTful APIs to a huge extent. We will be covering these in the next couple of parts of this tutorial series.

This post has been updated with contributions from Esther Vaati. Esther is a software developer and writer for Envato Tuts+.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.