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., ~/shared/flask-beers
(feel free to use a different destination as you see fit; for example, if you have a remote VM, putting it under shared/
wouldn’t be as helpful). 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 ~/shared/flask-beers
Now, we need to make sure you can access the website served by your VM.
- If you can get to your VM’s GUI directly (e.g., if you run VirtualBox and have installed GUI for it), you can simply start a Web browser inside your VM, and access the Play website at
http://localhost:5000/
. - If you have (or prefer having) only shell access to your VM, you can access the Play website from a browser running on your host as follows:
- If you are running a local VM using Vagrant, follow the instructions at Creating and Running VM Using VirtualBox/Vagrant to set up forwarding between your guest port 5000 and your host port 5000. You should then be able to access the Flask app at:
http://localhost:9000/
. - If you are running a Google Cloud VM, follow the instructions at Creating and Running VM on Google Cloud to find your VM’s external IP address (say it’s 123.45.67.89, for example), and to allow access to your VM’s port 5000. Then, you should be able to access the Flask application at http://123.45.67.89:5000/ (replace 123.45.67.89 with your VM’s external IP).
- If you are running a local VM using Vagrant, follow the instructions at Creating and Running VM Using VirtualBox/Vagrant to set up forwarding between your guest port 5000 and your host port 5000. You should then be able to access the Flask app at:
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 as instructed above, you should now be able to access the website from a browser running on your host. 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 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 namedbeers
, 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 torender_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 viewdrinker
inapp.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 codeDrinker.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 inDrinkerEditFormFactory
in this file (it is used in theedit_drinker
view inapp.py
and theedit_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 ofurl_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.
Rolling Your Own App
You can just modify the example Flask app directory (~/shared/flask-beers
). You can change the directory name to, for example, flask-mycoolapp
. Remember to modify the database configuration in config.py
.