Flask/Python Tips

Overview

Flask is a lightweight but powerful Web development framework based on Python. This document describes how to set up and run Flask’s development server, which will suffice for your course project and deployment to a limited user population. If you want to run Flask in a real production setting, follow these instructions.

We provide an example Flask application for our beloved beers database that you used in your homework. We assume that you already have this database set up; if not, run /opt/dbcourse/examples/db-beers/setup.sh in your VM.

Setting Up

First, refresh your VM by running the following:
/opt/dbcourse/sync.sh

Pick a folder for your Flask application, e.g., ~/flask-beers (feel free to use a different destination as you see fit). Hereafter we will refer to this folder as your “Flask app folder.” To install Flask on your VM and set up the example Flask app, run the command:
/opt/dbcourse/install/setup-flask.sh ~/flask-beers

Now cd into your app folder and you should see the code. Next we'll run this app.

Running the Website

To run the website, in your Flask app directory on the VM, simply issue the following command:
python app.py
A Flask/web server will start running. If you have set up your access to the VM correctly, you should see the server is listening on port 5000 of the VM. Visit this web app by visiting the following URL (replace xxxxx with your vm number) http://vcm-xxxxx.vm.duke.edu:5000. As you interact with the website, you will see various information and/or error messages in the VM shell.

You can keep your Flask server running and edit your app code on the side. In most case, your edits will be automatically reflected. If your changes introduce some error (such as a syntax error in your code), it may cause the server to exit with an error; you can note the error reported in the VM shell, fix it, and restart app.py. Sometimes you will see an error reported by the server in your browser (while the server continues to run); in that case you can do some limited form of debugging directly from your browser.

To stop your app, type CTRL-c in the VM shell; that will take you back to the shell’s command-line prompt.

A Flask Primer

Flask has following features that simplify Web development:

  • A MVC (model-view-controller) architecture, which separates data, presentation, and control flow.
    • The model “wraps” data stored in the database as Python objects, which can be manipulated (created, queried, and updated) by the controller and presented through the views.
    • The controller defines a set of views. Each view handles a Web request. It can interact with the database through the model, and feed relevant data to a Web page to be shown.
    • The Web pages are rendered in a Python-based template language called Jinja2. Templates can do some simple post-processing with the content to facilitate presentation (such as sorting and looping through a list of items). There is typically one template for each type of Web page. Flask templates can be thought of functions, and you can define a “base” template to factor out common structures/elements on your pages so it can be reused by other templates.
  • Mapping between URLs and views. Flask allows you to map URLs to views, which will take parameters passed in through the URL request as their input arguments. Flask also allows you to map views back to URLs. Withe the latter, your template code can generate links with parameters to other pages by referring to the appropriate views, without worrying about how to write the actual URLs.
  • Automatic mapping of object models to database tables using SQLAlchemy. You can specify models using Python classes; SQLAlchemy automatically handles their storage, retrieval, and update in a relational database. You can do (almost) all data manipulation on your Python objects without being concerned about SQL. However, we will not use the full capability of SQLAlchemy in our example app.

We now explain the relevant parts of a Flask app directory:

  • config.py: This configuration file stores (among other things) your database connection information. For this example, we connect to the PostgreSQL database named beers, which you used extensively in your assignments. You can change the connection information to work with other databases instead.
  • app.py: This is the main file that sets up the app and defines all the views and what URLs map to them (using @app.route decorators). Most views return with a call to render_template, which passes a bunch of data objects to a template file. app.py can also define additional Jinja2 “filters” that you can use in your templates (using @app.template_filter decorators).
  • models.py: This file defines how data stored in the database can be mapped to Python objects. With these definitions, SQLAlchemy can automatically retrieve data from the database as Python objects. For example, the view drinker in app.py retrieves a given drinker and associated information using just Python, without any SQL. For more complex queries and updates, however, SQLAlchemy can be quite convoluted and error-prone; you might be better off writing SQL instead. For example, we code Drinker.edit using SQL. Note the use of :param as placeholders for parameters to be passed into SQL; this method of constructing SQL queries is safer than trying to concatenate strings to make SQL queries yourself.
  • forms.py: This file defines forms objects on your website. Writing HTML forms manually can be painful. Luckily, Flask offers Flask-WTF to simplify this process: you can specify fields and how to validate them declaratively. Things become trickier if you want to generate your form structure dynamically (e.g., from a database); an example can be found in DrinkerEditFormFactory in this file (it is used in the edit_drinker view in app.py and the edit_drinker.html template).
  • templates/: This directory contains all your templates. Here, all templates “extends” layout.html, which controls the overall look of the website. Note the use of url_for to link to a another page instead of hardcoding the URL.
  • static/: This directory contains your static files, i.e., files such as images, CSS, and JavaScript that don’t need to be generated dynamically at runtime.