Flask

You can initialize a new flask application by using the Flask function with the name of the app. It is idiomatic to use the __name__ property for app object naming.

from flask import Flask 

app = Flask(__name__)

You can run your flask application with the .run method.

app.run()

You can run the application in debug mode so that it displays errors on the output webpages by setting the debug flag to True as an argument to run

app.run(debug=True)

You can specify a port to run on by passing in the port kwarg.

app.run(port=80)

Routes

You can define an application route by using the app.route method as a decorator for your controller functions. The argument to the route method is the url extension that will route to that controller function.

@app.route("/")
def index():
  return "Hello, world!"

You can define a function to run before each server request with before_request.

@app.before_request
def before():
  # do some set up etc. here

You can define a function to run after each server request with after_request. This passes a response object through to the inner implementation that needs to be handled in the argument definitions for the function. You must return the response in after_request to avoid server errors.

@app.after_request
def before(response):
  # do some tear down etc. here
  return response

You can define a POST route by using the methods property of routes. You can get standard data (such as a String) from a POST request by using the request object’s data field. This needs to be imported from flask to be usable.

from flask import request

@app.route("/add", methods=["POST"])
def add():
  data = request.data
  # do something with the data here

You can handle JSON data from a POST request by using the json property of the request object. JSON is parsed from the request object into python code as a dict. Don’t forget to add Content-Type: application/json before testing these requests manually.

@app.route("/echo", methods=["POST"])
def echo():
  json_data = request.json
  # do something with json_data dict here

You can can handle requests to a route with a single name but multiple methods by using the request.method property with a conditional.

@app.route("/multi", methods=["GET", "POST"])
def multi():
  if request.method == "POST":
    # do something with POST data
  else:
    # send response to GET request

Blueprints

You can split your flask application in a modular fashion using flask’s Blueprint module. This allows you to define routing in separate modules and then register them in your main app file.

# api.py module file
from flask import Blueprint

blueprint =  Blueprint('blueprint',  __name__)

@blueprint.route('/message')
def  show():
 return  "Hello, world!"

To register a blueprint in your main flask app you must import the module file that contains the blue print and then use the register_blueprint method. Once registered if the user navigates to the url extensions defined in the blueprints they will be served via those controllers.

# app.py
from flask import Flask
from api import api

app = Flask(__name__)
app.register_blueprint(api.blueprint)

You can prefix all of the routes a blueprint with a master route by using the url_prefix property when registering a blueprint. In the example below this now means the message route define in the api blueprint will be available at /api/message to users.

# app.py
app.register_blueprint(api.blueprint, url_prefix="/api")

JSON

You can send JSON responses by using the jsonify method. This accepts JSON formatted data (or a Python dict) as its argument between {} curly braces. Keys and values must be in string format.

jsonify(
  {
    "codec": "73-ZXX14", # key value pairs
    "users": [ # arrays
      "Nelson",
      "Lauren",
      "Vlad"
    ],
    "scheme": { # nested objects
      "platform": "spectrum",
      "version": "1.1.2"
    }
  }
)

Templating

You can render and return a page template by importing the render_template function from flask and returning it in your flask route with the path to the template you want to render as the argument. The render_template function will look for a directory called templates in the directory that the app is being run from to find a file path to the file you want to render.

from flask import render_template

# --snip--

@app.get("/")
def index():
  return render_template("index.html")

Jinja

Flask uses the jinja2 templating engine.

You can embed jinja code for templating and logic by using the {[%] [%]} curly brace, percent syntax indicators.

{[%]  body [%]}
	<!-- code here -->
{[%] endblock [%]}

You can interpolate code results as a string using `` double curly braces.

<link rel="stylesheet" href="">

Templates

The jinja2 engine works by inheriting from other templates by name and then use named blocks to insert content. For example a very simple template might look like the base.html file below which defines a block called body.

<!-- base.html -->
<html  lang="en">
  <head>
    <meta  charset="UTF-8">
    <meta  name="viewport"  content="width=device-width, initial-scale=1.0">
    </head>
  <body>
    {[%] block body [%]}{[%] endblock [%]}
  </body>
</html>

To inherit from a template use the extends keyword followed by the name of the template as a string.

<!-- index.html -->
{[%] extends 'base.html' [%]}

You can insert content for a templated block by inserting regular HTML content between the block and endblock tags. This will then inject that content into the template when it is returned by flask.

<!-- index.html -->
{[%] block body [%]}
  <h1>Hello, world!</h1>
{[%] endblock [%]}

CSS and JS

You can import static content such as CSS and Javascript by setting their href and src respectively interpolating a file path using Jinja’s `` interpolation code and Flask’s url_for method which takes the name of the static directory as its first argument and then a file path to the static file within that folder. The example below loads main.css from the static/css/ directory and index.js from the static/js folder and inserts the correct file paths thus loading the resources.

<link  rel="stylesheet"  href="">
<script  src=""></script>

SQLAlchemy and Database Sessions

One way to control database sessions for different controller routes is to open and close them in the before_reuqest and after_request functions then make the scope session object available to the route using it via the global scope of your flask application. In the code below app.py sets up opening and closing sessions before each request to the server, the individual blueprint routes can then use the session as required by importing the g variable from flask. Flask g isn’t really global in the traditional sense, while it encompasses the application context, each new request wipes the old g scope and keeps it just for that request.

# app.py
from database import Session # import the main Session object
from flask import Flask, g

# --snip--

@app.before_request
def before():
  g.session = Session()

@app.after_request
def after(response):
  g.session.close()

# controller.py
# some other controller blueprint with routes
from flask import g

# --snip--

@blueprint.route("/users")
def save_user():
  user = User(name="Jimothy", age=10)
  g.session.add(user)
  g.session.commit()

Testing

You can test your flask application by creating a pytest.fixture that initialises the app in "TESTING" mode (this suppresses exception handling so that the test environment can more easily manage errors with meaningful messages) and then yield or return a test_client() to your test functions. Below is the simplest example of a test set up for a flask application. This would usually be longer with database integration etc.

import pytest
from app import app # import a flask app that has been initialised in your main file

@pytest.fixture
def client():
  app.config["TESTING"] = True

  with app.test_client() as client:
    yield client # send the test client to test methods

You can test a flask route by calling the get method on a client route. This also works with blueprint define routes, you just need to include the absolute url extension to that route. You can access and test against the status of a response object, this comes in the form of a string.

def test_index(client):
  response = client.get("/")
  assert response.status == '200 OK'

You can access the data of a response by using the data property.

def test_index(client):
  response = client.get("/")
  assert response.data != None

You can test the string data of that response which comes in the form of byte data and so needs to be prepended by the b character when testing strings to indicate it is a byte string literal.

def test_index(client):
  response = client.get("/")
  assert response.data == b'This is a message'

You test a POST route by using post method on the flask test_client object and passing data. The example below shows a route that reverses a string that is sent to it.

def test_post_data(client):
  response = client.post("/reverse", data="Mandelbrot")
  assert response.data == b'torblednaM'

You can send JSON to post routes by adding a json.dumped dict with content_type set to application/json. The /echo route below accepts JSON and send back as a string whatever value is stored in the foo key.

import json

def test_post_json(client):
  response = client.post("/echo", 
    json.dumps(dict(foo='bar'), 
    content_type='application/json')
  response.json == b'bar'