This tutorial is out of date! Try my longer, updated Flask-SQLite webapp tutorial here
If we were normal people, going to make a normal website, we might start off our website with a real big header proclaiming how great it is. The HTML we’d write might look like this:
But since we’re professionals, and we’re data wranglers, and we’re specifically data wrangling school data, we’ll probably start it off with the name of a school.
But then eventually we’ll have to make one about a different school, which will have a completely different headline associated with it
and if we have several hundred high schools in NYC it is going to take a very long time, much less if we want to expand to the thousands and thousands of schools across America.
Luckily, we don’t have to write that HTML. Instead, we write Python code that writes the HTML.
That Python code looks into a database, finds the name of the school we’re looking at, and slaps the
<h1>PS 15 Roberto Clemente</h1> right there on the page. If we’re looking at a different school, it gets a different name from the database, and the HTML gets a different name inside of the
The backend can be any sort of programming language, and can be more or less complicated based on what it’s intended to do. Today we’ve decided we’re going with Python, and we’re using a rather simple framework called Flask
Flask is a web microframework built in Python.
Another popular web framework you might have heard of is Ruby on Rails (which, of course, uses Ruby).
While you can put everything in your Flask project into a single file, it’s most always better to organize it into multiple files - put your Python code over here, put your HTML templates over there, some other stuff somewhere else.
Our project is going to be called
nyc-schools. Add a folder called
static and another one called
nyc-schools/ app.py static/ templates/
templates is the templated versions of the dynamically generated web pages (i.e., the previously-mentioned
<h1> with a placeholder inside of it).
app.py is our application file. It should contain the following code:
From terminal, in the
nyc-schools directory, run the command
And then do me the favor of visiting http://127.0.0.1:5000 to check out your freshly minted web application.
So you know how we mashed up a bunch of HTML in the “Hello world” section? That’s horrid, and we should be drawn and quartered for it. HTML belongs in an
.html file, and we’re going to put it there before anyone notices.
Add a file called
index.html into your
templates folder and have it contain the text
<h1>Hello world</h1>. We’re going to render that page instead of just sending back some text, which takes two changes:
app.py’s index function to read as follows
Add a new import line to the top of
Now refresh. Cool, right? How nothing changes?
render_template is just reaching down into the
templates/ directory, grabbing
index.html, and rendering it instead of the text we had there before.
To make use of this (kind of), let’s edit the code in index.html just to make a list of a few schools.
Let’s say you have a cool variable in our application, like what we think the number of schools is in NYC.
You can actually send that value to
index.html, and then use it there to fill in empty spots in the template.
First we’ll edit our
render_template to send the information to the template.
Then we’ll edit our
index.html to use the variable, by using `` as a placeholder, with the variable name inside.
But that number doesn’t seem quite right. How are we going to change it?
A database is going to be the saving grace of this project - by pulling information out of the database, we don’t have to guess at the number of schools, nor do we have to type each and every one of their names out. It’s a paradise!
We’re going to use our
models.py file from the peewee tutorial - go ahead and copy it into the
nyc-schools/ directory, along with
Using our database in
app.py is the same as when we imported it to learn how peewee works. Add another import to the top of the file:
Now we can use
Score just like we did before! In order to get an accurate count of the number of schools, we’re going to use
School.select().count(). It selects all of the schools, then laboriously counts them.
Refresh! Rejoice! 437, right?
I’m still angry about typing out all of those school names in the
index.html - peewee can help with that, as well. Instead of just sending boring variables like integers to the template, we can send an entire selection of schools.
Then in our
index.html, we can loop through them all and display the
Then edit our
index() to pull all of the schools out of the database. We’ll pull them down in alphabetical order.
Step three: Send them to the template
Now we have all the schools, we just need to send them to the template, and then use them in the template. Edit
index one more time to send them to the template:
Cool, ‘eh? But it just isn’t enough, I know. If we’re going to win a Pulitzer we need individual school pages.
If we take a look at our
index, there’s a suspicious line right about it:
@app.route('/') is a route - a URL you can type in to get to a specific function in the Flask app. That one defines
/ and tells Flask to execute
index() whenever someone runs across it. Let’s make another one!
And now you should be able to visit http://127.0.0.1:5000/schools/clemente and see that route run!
Of course, we should probably set up a template for it. Let’s call it
school.html and put it into
app.py to point to the template:
Refresh to double-check it worked, and we’re on our way to the next step!