Effortless REST with Flask, Part 1

A new way to look at an API

Qualities of a production-ready API

  1. Authentication — How can I identify users and grant them access to the API?
  2. Authorization — How can I properly give permissions within the API?
  3. Database Connections and Management — How do I get underlying data to serve via the API?
  4. Documentation — How do I tell my API clients how to use the API?
  5. Proper Logging — What feedback should my API give me about its current processes?

Building a Simple API

from flask import Flaskapp = Flask(__name__)@app.route('/')def hello_world():return 'Hello, World!

Packages and plugins

  1. Flask-RestX (Previously Flask-RestPlus) — Helps to build an organized REST API quickly with documentation
  2. Flask SQLAlchemy — The ORM layer to help fetch data from a relational database
  3. Flask Praetorian — A JWT based API authentication and authorization library
pip install -r requiremnts.txt

Main Flask app

"Main Flask App"# pylint: disable=import-outside-toplevelfrom logging import Loggerfrom typing import Listfrom flask import Flask, jsonify, abort, request# Application Factory# https://flask.palletsprojects.com/en/1.1.x/patterns/appfactories/def create_app(config_name: str) -> Flask:"""Create the Flask applicationArgs:config_name (str): Config name mapping to Config ClassReturns:[Flask]: Flask Application"""from app.config import config_by_name# Create the appapp = Flask(__name__)# Log the current config name being used and setup app with the configapp.logger.debug(f"CONFIG NAME: {config_name}")config = config_by_name[config_name]app.config.from_object(config)@app.route("/")def hello_world() -> str:  # pylint: disable=unused-variablereturn "Hello World!"return app

Configuring your Flask app

""" Provide the capability to configure the app based on the target environment. """# Flask configs: https://flask.palletsprojects.com/en/1.1.x/config/# Flask-SqlALchemy configs: https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/import osfrom typing import DictBASEDIR = os.path.abspath(os.path.dirname(__file__))class Config:""" Base config. """DEBUG: bool = FalseSECRET_KEY: str = "top secret"class TestingConfig(Config):""" Testing config. """# Override defaults from parent.#DEBUG: bool = TrueSECRET_KEY: str = "my_precious_secret_key"#  Exceptions are propagated rather than handled by the the app's error handlers.TESTING: bool = Trueclass DevelopmentConfig(Config):""" A config to be used for development, use mocks so you don't need a DB. """# Override defaults from parent.#DEBUG: bool = TrueSECRET_KEY: str = os.getenv("SECRET_KEY", "my_precious_development_secret_key")class ProductionConfig(Config):""" Production config. """# Inherits defaults from parent.SECRET_KEY: str = os.getenv("SECRET_KEY", "dc89aa6c-93e7-474d-a55a-b2113b25fc16")config_by_name = dict(  # pylint: disable=invalid-namedev=DevelopmentConfig, test=TestingConfig, prod=ProductionConfig)

Starting your Flask app

  1. Run the application using the `flask` CLI command
  2. Run the application using a web server such as gunicorn
export FLASK_ENV=development &&export FLASK_APP="app:create_app('dev')" &&flask run --host=127.0.0.1
gunicorn --bind 127.0.0.1:5000 --workers 2 "app:create_app('prod')"

Say hello to Invoke

Invoke start
Invoke start -w

What a great start!

--

--

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