How to build a REST API with Flask

Flask is a framework that is widely used to create APIs in Python. Flask is a simple yet powerful web framework that is designed to help us get started quickly and easily, with the ability to scale up to complex applications. Flask is called ‘micro’ because it was built with a simple but extensible core.

An API is a contract between an information provider and an information user that establishes the content required by the consumer and the content required by the producer.

REST stands for Representational State Transfer. A RESTFUL API allows for interaction with RESTful web services by conforming to the constraints of REST architectural style.

Install dependencies

pip install pipenv
pipenv shell
pipenv install Flask

Start a flask app

app.py

from flask import Flask

app = Flask(__name__)

@app.route('/', method=['GET'])
def home():
   return 'Hello World'

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

Save the file above as app.py; this does not really matter so far, as it is a Python file.

In the terminal, type the following (or whatever you called your Python file):

python app.py

Launch any web browser and go to the following to see the app in action:

 http://localhost:5000

Return a JSON serializable output

If you are building an API in a Flask app, then the return value from any function should be JSON serializable. You can use jsonify to make your output JSON serializable. The jsonify function wraps json.dumps() and turns the JSON output into a response object with application/JSON mime-type.

Before we start to code, we will use flask-marshmallow.

What is flask-marshmallow?

flask-marshmallow is a thin integration layer for Flask and marshmallow (an object serialization/deserialization library) that adds additional features to marshmallow, including URL and hyperlink fields for HATEOAS-ready APIs.

Type the command below in the terminal to install flask-marshmallow:

pipenv install flask-marshmallow

Now, let’s add some more code to the app.py file.

from flask import Flask,request,jsonify
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_marshmallow import Marshmallow
import os
from pprint import pprint


app = Flask(__name__)

basedir = os.path.abspath(os.path.dirname(__file__))

#database configuration
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'db.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

#referencing SQLAlchemcy
db = SQLAlchemy(app)

#referencing marshmallow
ma = Marshmallow(app)

#model
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name =db.Column(db.String(100))
    email = db.Column(db.String(100), unique=True)
    date_created = db.Column(db.DateTime, nullable=False,default=datetime.utcnow)

    def __init__(self, name, email):
        self.name = name
        self.email = email
    

class UserSchema(ma.Schema):
    class Meta:
        #Fields to expose
        fields = ("id","name","email","date_created", "_links")

    #Smart hyperlinking
    _links = ma.Hyperlinks(
    #make sure your function names are the same like 
    #interms of single data fucntion(e.g def singleUser: is singleUser for "self")
    #and many data fucntion(e.g def home: is called home in the "collection")
    #if not there will be an error in the smart hyperlinking
        {"self": ma.URLFor("singleUser", id="<id>"), "collection": ma.URLFor("home")}
        
    )


user_schema = UserSchema()
users_schema = UserSchema(many=True)

#get all users
@app.route('/', methods=['GET'])
def home():
    all_Users = User.query.all()
    result = users_schema.dump(all_Users)
    return jsonify(result)

#get a particular user
@app.route('/<id>', methods=['GET'])
def singleUser(id):
    single_User = User.query.get(id)
    return user_schema.jsonify(single_User)
     
#add user
@app.route('/add', methods=['POST'])
def addUser():
    name  = request.json['name']
    email = request.json['email']
  
    new_User  = User(name=name,email=email)
    if User.query.filter_by(email=email).count() == 0:
        db.session.add(new_User)
        db.session.commit()
        return user_schema.jsonify(new_User)
    else:
        return "Email already exist"
        
#update the user  
@app.route('/<id>', methods=['PUT'])
def updateUser(id):
    update_User = User.query.get(id)
    name  = request.json['name']
    email = request.json['email']
    update_User.name = name
    update_User.email = email
    db.session.commit()
    return user_schema.jsonify(update_User)
 

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

Go to your terminal and run:

python
from app import db
db.create_all()
exit()

Next, run:

python app.py

Then, go to your browser and type or copy and paste this link to see the app in action:

http://127.0.0.1:5000/

You will see something like this:

Here is a link to the GitHub repo.

Free Resources