Making a Flask Web App 101

Deliverables

Due date: Thursday, May 14

Create a folder in your compjour-hw repo named: flask-app-101.

Follow a directory structure similar (but modify as needed) to the demo app found in the First News App tutorial:

|-- compjour-hw/
    |-- flask-app-101/
       |-- app.py
       |-- static/
           |--- whatever-datafiles.etc
       |-- templates/
           |-- index.html
           |-- detail.html
       (etc)

At a minimum, your app must consist of:

  • index.html - contains a listing (such as a HTML table) of data entries, and each data entry is clickable.
  • detail.html - this is the template page for each specific data entry
  • app.py - This is required for the app to even work, including its routes (e.g. detail and index. You can cram all the data-loading logic in here too. Or you can put those in separate files and import them.

On your own computer, when you go to the command-line and change to your compjour-hw/homework/flask-app-101 directory, the following command should properly start up a webserver and launch the app on your own computer:

python app.py

You can include similar front-end code as found in the First News App tutorial to render a map.

The data

For your app, Iw ant something similar to the First News App tutorial – you can even copy its front-end code used to make a map. However, you must use a different source of data (preferably something mappable) – i.e. not the Los Angeles riots.

Suggestions include:

Some background

A "web application" is essentially a program that serves up webpages. The path described for this homework assignment is one of many, many ways to do it. The libraries that we will be using (which should be included in your Anaconda installation of Python):

  • Jinja - a HTML templating language: you define some static HTML code and put in some placeholders, and Jinja replaces those placeholders with data.
  • Flask - a "microframework" for web applications.

The First News App tutorial

As a reference, we'll be using the excellent First News App guide, as created by Ben Welsh as a training session for Investigative Reporters and Editors and the National Institute for Computer-Assisted Reporting.

You can see the live demo app here: ireapps.github.io/first-news-app/build/index.html

Start from scratch

I recommend just following the First News App tutorial verbatim and re-writing it from scratch. You can download the la-riots-deaths.csv here.

Don't put this in your homework folder…put it somewhere else (i.e. ~/Desktop/myapp or /tmp/myapp.

Then, when you're ready to complete the homework, re-create the app, modify as you see fit.

Key takeaways

A web app is just code

The logic and code needed to open a file, or to turn a JSON or CSV or anything to a Python data structure, is the same for a web app as it is for anything else you'd write in Python.

The view consists of static HTML and a templating language

Think of past homework assignments in which you've taken a bunch of HTML and replaced a single string in it (i.e. USAJobs Midterm Part 1, with the Google Charts). This web app is no different:

<td>{{ obj.address }}</td>

The <td> and </td> is the HTML code. And the {{ obj.address }} is just the format specified by the Jinja templating language: think of it as a more formal version of this:

"<td>%s</td>" % obj.address

It requires a webserver

In the tutorial, you'll get to the part when you need to do this at the Terminal command-line: (it will not work to run it from Sublime Text)

python app.py

Then you're told to visit the address localhost:5000 – what makes a Flask app different than just some plain Python code is that it is designed to run on a web server…which is, well, just a computer except one configured to accept HTTP requests. For our limited practical purposes, this means we have to run a webserver to test the app…and that is part of what the app.py code does when running it locally: it opens up a port on your machine (by default, 5000), and you can visit this makeshift webserver in a browser by going to http://localhost:5000

You can read more about it in the Flask Quick Start docs.

View and app code are separate

The files in /templates are considered the views of the app. And app.py contains the app's main logic, sometimes referred to the controller of the app. Notice how they're kept completely separate from each other. This is a key feature in most non-trivial web applications.

A few caveats First News App tutorial

This tutorial was written for an audience with less familiarity with Python/programming than you, and makes a few assumptions about your system that odn't apply:

  • Ignore everything about virtualenv. We don't need it.
  • Ignore the pip install flask part, it should already be installed (via Anaconda).
  • The touch app.py at the command-line simply creates a new file. You can run it if you like, or just create files through Sublime Text.
  • In fact, you should make a new project folder (call it myapp or something, and stick it in ~/Desktop or ~/Downloads). Then open that folder with Sublime Text and work from there.
  • When making the test/demo app, ignore the parts about git. You don't need to commit this app. And for your actual app, just put it in compjour-hw and commit it the normal way (i.e. via your Github desktop app).
  • Python 2.x/3.x compatibility problem: Where the tutorial says to use this:

         csv_file = open(csv_path, 'rb')
    

    Use this instead (i.e. omit the b, which stands for "bytes"):

        csv_file = open(csv_path, 'r')
    
  • You can ignore the Act 5: Hello Internet steps, which describe how to "freeze" the app so that it can live as static HTML. We'll get to that later.

Test the tutorial, make it your own

Still confused about how variables and functions work? Make an effort to change every variable and function name that you can. In fact, you can pretty much change everything, though the snippet below shows what you should keep the same to be safe:

from flask import Flask
from flask import render_template
app = Flask(__name__)

@app.route("/")

def index():
  # etc etc
  return render_template(etc etc etc fill your variables here)

@app.route("/<some_varname>/")
def detail(some_varname):
    template = 'detail.html'


if __name__ == '__main__':
    app.run(debug = True, use_reloader = True)

In other words, an alternative writeup of the demo app code would look like this:

from flask import Flask
from flask import render_template
app = Flask(__name__)
import csv

def get_csv():
    p = './static/la-riots-deaths.csv'
    f = open(p, 'r')
    return list(csv.DictReader(f))

@app.route("/")
def index():
    template = 'index.html'
    deathlist = get_csv()
    return render_template(template, deaths = deathlist)

@app.route("/<death_id>/")
def detail(row_id):
    template = 'detail.html'
    deathlist = get_csv()
    for death in deathlist:
        if death['id'] == death_id:
            return render_template(template, object = death)

if __name__ == '__main__':
    app.run(debug = True, use_reloader = True)