Flask : A Python based micro web framework

Flask is a nifty module that has a peculiar origin :

“It came out of an April Fool’s joke but proved popular enough to make into a serious application in its own right.” Armin Ronacher - Creator of Flask

Despite it’s humble beginnings, Flask has grown into an extremely versatile web application framework, and is used for both tiny web server projects up to serious multi-developer projects used by a large userbase.

Web basics

The HyperText Transfer Protocol (HTTP) has a number of request methods. The oldest and most common is GET which is often used to simply retrieve data from the server.

The other common method is POST, used for e.g. “posting” data to the server.

Additional methods include PUT, DELETE, HEAD, PATCH and several more.

Why Flask?

So why might we be interested in writing a web-application? In essence this comes down to “why might we be interested in a centralized user interface model”?

From my experience, the answer is that there are use-cases where developing and distributing traditional User Interfaces is not a good model.

For example, you might want to provide users access to data that you don’t want to have replicated each time a new user wants to access it.

Alternatively you might be actively developing the application used, and not want to continuously remind users to upgrade to the latest version of your software.

Even when you don’t have users, you might prefer to develop a server interface so that you don’t have to carry data around with you to conferences / when away from the office.

Whatever the reason web interfaces are growing in popularity, and the Python community has responded to that demand.

Other popular web frameworks for Python include Django, Pyramid, CherryPy, and Web2Py to name but a few.

Sample responses

The following iframes show embedded, real-time responses from a running Flask application server.

Basic response : /

One of the most basic respones is a simple line of text showing that the server is working correctly.

<iframe height=100 src=”http://apollo.ex.ac.uk:8000/”></iframe>

URL data : /42

Passing information as a URL parameter is one of the simplest ways of transfering data to the server.

This response shows that the information is received on the server, and the generated response incorporates this data.

<iframe height=100 src=”http://apollo.ex.ac.uk:8000/42”></iframe>

Interactivity: /power

One of the most common ways of interacting with a server is via a form; this response displays a form; and subsequently generates a response from the GET parameters - parameters that get passed into the request url in a special format.

<iframe height=100 src=”http://apollo.ex.ac.uk:8000/power”></iframe>

Displaying a dynamically generated plot: /plot

In order to use web interfaces for science, we need to integrate scientific content; in this case a simple plot is generated dynamically each time the page is visited and rendered in the response.

<iframe width=400 height=400 src=”http://apollo.ex.ac.uk:8000/plot”></iframe>

Displaying a dynamically generated image: /random

In addition to generating line plots of 1d data, we can generate 2d data and display it using images/heatmaps.

<iframe width=400 height=400 src=”http://apollo.ex.ac.uk:8000/random”></iframe>

Displaying a plot with a javascript plotting library: /plotly

In-browser visualizations are becoming increasingly sophisticated and able to rival native desktop applications.

Plotly incorporates the powerful d3.js vector graphics library and stack.gl (on top of webGL) to bring a large range of scientific plots and visualizations to the browser.

<iframe height=400 width=800 src=”http://apollo.ex.ac.uk:8000/plotly”></iframe>

<iframe height=800 width=800 src=”http://apollo.ex.ac.uk:8000/plotly_with_get/3d”></iframe>

Getting started with Flask

Getting Flask to display a “Hello, World” style message is really easy!

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

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

A quick dissection:

  • import the Flask class from the flask module.
  • Create a Flask object and call it app
  • Use the app.route decorator supplying the route url
  • Define the route function which in this case returns the string “Hello Workd!”
  • Use the if __name__ == "__main__":-block to run the app.

A route is a url that the application will render; the “root” url is rendered when no additional relative url path is given.

E.g. when we navigate to the Exeter university domain:

http://www.exeter.ac.uk/

we get the home page. This is at the root of the exeter.ac.uk domain.

If we then click on the research link, we are directed to the relative path /research/ (the full url is http://www.exeter.ac.uk/), and are displayed new content that pertains to research being done at the university.

Exercise : Your first route

Create a new script and copy and paste the code above.

Edit the root (aka home) rendering function to display the text

Hello!

Welcome to YOURNAME's site

(replace YOURNAME with your name)

Note that you can’t use newline characters (“\n”) as these don’t create line breaks in web-pages; instead use the html code for a line break :

<br>

Next, add another route at “/about” that renders a small information text explaining that this site is part of a python exercise.

Reacting to user requests

Via url get parameters: Variable routes

As well as static routes, Flask makes it’s easy to add routes that accept variables, such as

/file/001
/project/12/user/133/
/search/larynx

ie one or more numerical fields, or string fields.

The syntax for adding a variable route like this is straight-forward

@app.route('/project/<int:project_id>')
def show_user_profile(project_id):
    return 'You selected project %d' % project_id

If no converter is specified (int above), the variable will be passed in as a string. The converter can be one of int, float, path, which will convert the strint to integers, floating point numbers, or a path (i.e. string which can include a forward-slash).

Exercise : A scientific visualization

Create a flask app similar to the “Hello, world” sample, but add in a route that generates and serves a randomly generated sequence of number and smoothes those numbers using a gaussian filter (you will need to refer back to the Numpy and Scipy sections!).

Add in a variable to the route, to allow the user to specify the width (sigma) for the gaussian smoothing.

Bonus section

Also generate a plot of the data as well as the smoothed line, and serve the plot. There are two main ways to do this; either create a real file, and serve that, or generate an in memory file and convert the in-memory file to a base-64 encoded string; the base-64 encoded string can be embedded in the returned string and will show up as an image.

Adding user interface elements

While not technically part of learning about Flask, one of the motivations for using Flask is to provide a user interface for our users.

As such, it’s worth pointing out, that many of the standard classical GUI elements have HTML equivalents;

The <input> element provides input boxes for:

  • Text by setting type=text
  • Numbers by setting type=number
  • Button by setting type=button
  • Date by setting type=date
  • Color by setting type=color
  • Password box by setting type=password
  • Radio button by setting type=radio
  • Slider by setting type=range
  • …and more!

In addition, there’s a select tag for defining a drop down list, progress for displaying a progress bar, and libraries such as JQuery-UI or Bootstrap define many more user interface elements.

In terms of graphical elements, in addition to the img tag for static images and the video tag to stream videos, there also a drawable canvas tag for general 2d graphics, which now also supports 3D graphics support via the WebGL specification.

Additional concerns

Using Sessions to store and retrieve information

The internet (meaning the HTML protocol in this case) is often referred to as stateless. This means the the state of information is not automatically retained between refreshes of a site (or navigation between child pages).

Instead, website developers have to use either client-side or server-side methods to store information between these operations.

Most heavy-duty state storage is done via server databases, but small pieces of information are often stored on the client (i.e. by your browser); the main place such information is stored is in cookies.

To start storing information between page calls in Flask, we’re going to use the session storage object, which can be accessed as if it were a dictionary (i.e. using keys to access values.

As an example, if we modify the home route of the initial example as follows

from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'SUPERSECRETKEY'

@app.route('/')
def hello_world():
    if "visits" not in session:
        session["visits"] = 1
    else:
        session["visits"] += 1
    return 'Hello World! (%d times)'%num

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

We will see

Hello World! (1 times)

when we first visit the site.

However, if we press refresh, we will get

Hello World! (2 times)

, 3 times on the next and so on.

Beyond basic Flask

While generating data and responding to input using a “traditional” server model works and is how many websites still operate, most modern websites now incorporate a reactive element.

This means that instead of a classic request-response cycle (updated to include the AJAX model of not refreshing a whole page), many sites now use websockets, which provide bi-directional messaging between client and server to allow for real-time update of browser content.

Flask extensions exist to work with websockets, allowing developers to create truly reactive experiences.

Tornado (Python) and NodeJS (which allows for a pure Javascript developement environment instead of switching between a server-side language like Python or Ruby, and client-side Javascript) both offer websockets as default.

Lastly, meteor, which is built “on top” of NodeJS, is a single source web application framework which aims to provide an environment for seamlessly writing web applications where the distinction between and server and client is virtually removed.

Using a front-end Javascript framework

Initially websites were mainly displays of static information, and any interactivity was afforded by sending information back to the server (via a form), and having a new, but equally static page returned (containing mainly static HTML elements and text).

However as well as rendering these HTML elements, the front-end of modern web-applications are “brought to life” by Javascript, which provides the majority of the dynamical aspects to web apps.

Initially this was done through pure Javascript, followed by the massively popular JQuery library which provided quick and convenient methods for dynamical (client-side) webpage manipulations.

More recently, impressive client-side frameworks have emerged, such as Google’s AngularJS, Backbone.js, Ember.js, and React by Facebook and Instagram. These add either a full Model-View-Controller (MVC) framework to the front-end of a website, or parts of it.

The MVC architectural pattern for implementing user interfaces centres around dividing “… a given software application into three interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user”.

In short, instead of the client receiving mostly static pages, nowadays most larger websites offer full client-side web applications that are essentially programs running inside browsers, which still synchronize data back and fore with the server.

There are several Flask extensions that make working with such frameworks straightforward, such as Flask-Resful for creating a RESTful web app “endpoint”, as well as template projects showing how to combine Flask with e.g. Angular.

If you would like to know more about getting started with writing a full web application, drop me an email and I’ll give you some tips on how to get started!