Analytics Vidhya
Published in

Analytics Vidhya

Building REST APIs using Flask-RESTPlus, SQLAlchemy & Marshmallow

flask-Restplus with SqlAlchemy

Flask and Flask-RestPlus

  • It supports namespaces, which are ways of creating prefixes and structuring the code.
  • It has a full solution for parsing and validating the input parameters. This means that we have an easy way of dealing with endpoints that require several parameters and validate them.
  • Its best feature is the ability to automatically generate interactive documentation for our API using Swagger UI.

Flask-Marshmallow

Flask-SQLAlchemy

Swagger UI

  1. Setup and Installation
  2. Integrate Flask-Marshmallow
  3. Integrate Flask-SQLAlchemy
  4. Create Models
  5. Create Schemas
  6. Create Resources
  7. Application Entry Point
  8. Test the API

Prerequisites

1. Setup and Installation

$ cd /path/to/my/workspace/
$ mkdir python-sample-flask-application
$ cd python-sample-flask-application
pipenv shell
pipenv install flask-restplus
pipenv install flask-marshmallow
pipenv install flask-sqlalchemy
pipenv install marshmallow-sqlalchemy
  • Pipfile contains all the names of the dependencies we just installed.
  • Pipfile.lock is intended to specify, based on the dependencies present in Pipfile, which specific version of those should be used, avoiding the risks of automatically upgrading dependencies that depend upon each other and breaking your project dependency tree.
flask-restplus = "==0.13.0"
flask-marshmallow = "==0.14.0"
flask-sqlalchemy = "==2.4.4"
marshmallow-sqlalchemy = "==0.24.1"
"werkzeug": {
"hashes": [
"sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43",
"sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"
],
"version": "==1.0.1"
}
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
flask-restplus = "==0.13.0"
flask-marshmallow = "==0.14.0"
werkzeug = "==0.16.1"
flask-sqlalchemy = "==2.4.4"
marshmallow-sqlalchemy = "==0.24.1"

[requires]
python_version = "3.7"
pipenv update

2. Integrate Flask-Marshmallow

from flask_marshmallow import Marshmallow
ma = Marshmallow()

3. Integrate Flask-SQLAlchemy

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

4. Create Database Models

  • We started off by creating the ItemModel class in line 5.
  • In line 6, we declared the table name items where this model will be mapped to.
  • From line 8 to 10, we defined the table columns along with their dataType.
  • We defined the relationship with StoreModel in line 12 and 13.
  • From line 26 to 36, we added some helper methods to perform search operation on items table.
  • From line 38 to 40, we defined the save_to_db method to save the items in the database.
  • From line 42 to 44, we defined the delete_from_db method to delete the items from the database.
Store.py
  • We started off by creating the StoreModel class in line 5.
  • In line 6, we declared the table name stores where this model will be mapped to.
  • From line 7 to 8, we defined the table columns along with their dataType.
  • We defined the relationship with ItemModel in line 10.
  • From line 17 to 27, we added some helper methods to perform search operation on stores table.
  • From line 29 to 31, we defined the save_to_db method to save the stores in the database.
  • From line 33 to 35, we defined the delete_from_db method to delete the stores from the database.
Entity Diagram

5. Create Schemas

ItemSchema.py
StoreSchema.py

6. Create Resources

6.1 Item.py

Item-Resource.py
  • Item is used to perform operations on the Item table using the id field.
  • ItemList is used to create an Item or return all the items present in the Item table.
request-body
item = items_ns.model('Item', {
'name': fields.String('Name of the Item'),
'price': fields.Float(0.00),
'store_id': fields.Integer
})
@item_ns.expect(item)
item_ns = Namespace('item', description='Item related operations')
items_ns = Namespace('items', description='Items related operations')

6.2 Store.py

Store-Resource.py
  • Store is used to perform operations on Store table using the id field.
  • StoreList is used to create a Store or return all the stores present in the Store table.
store = stores_ns.model('Store', {
'name': fields.String('Name of the Store')
})
@stores_ns.expect(store)
store_ns = Namespace('store', description='Store related operations')
stores_ns = Namespace('stores', description='Stores related operations')

7. Application Entry Point

  • We started off by creating a Flask WSGI application in line 10.
  • In line 11, we created a blueprint instance by passing name ,import_name and url_prefix. Flask blueprint, helps us to host the API under the /api URL prefix. This enables us to separate the API part of our application from other parts. It’s a popular way of designing modular applications.
  • API is the main entry point for the Flask-RESTPlus application resources. Hence, we have initialized it with the blueprint in line 12. Here, we have overridden the default Swagger UI documentation location by passing an additional parameter doc=/doc to the initializer.
  • The next step is to register the Blueprint with our Flask app in line 13.
  • From line 14 to 16 we have added some configuration related to SQLAlchemy. Here, we are using SQLite DB. These configurations are required to link SQLite DB with SQLAlchemy. data.db is the name of the DB File.
  • From line 18 to 21 we added all the namespaces defined earlier to the list of namespaces in the API instance. If you build the API using the namespaces composition, it becomes simpler to scale it to multiple APIs, when you have to maintain multiple versions of an API.
  • From line 24 to 26 we have used the db instance (from file db.py) to create the DB file along with the tables before the user accesses the server.
  • The @api.errorhandler decorator allows us to register a specific handler for a given exception (or any exceptions inherited from it), in the same manner that we can do with Flask/Blueprint @errorhandler decorator.
  • From line 34 to 37 we called the add_resource method on the namespaces to bring the required resources under a given namespace. We should also ensure that the name of the namespace replaces the name of the resource, so endpoints can simply refer to the URL specified as an argument. Here, for example item_ns.add_resource(Item,'/<int:id>') Item resource is available at the endpoint/item/{id}name ofitem_ns which is item followed by /id. We can notice the changes in the Swagger UI as follows:
Item-Swagger-UI
  • In line 40 and line 41 integrate SQLAlchemy and Marshmallow.
  • Finally, in line 42 we start the application at port=5000 by executing the following command.
python app.py
Project Structure

8. Test the API

Swagger-UI
Store-Create
Fetch-Stores
Add-Item
fetch-stores

References & Useful Readings

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store