2 Getting started with Flask

We’re going to start by firing up a basic, no-frills web application using Flask. Flask is a web application framework, which means it does all the complicated parts of building a website and leaves you with the easy bits (relatively speaking). That definitely doesn’t make any sense right now, but that’s perfectly fine, because you’re about to see how it works!

2.1 Baby’s first web app

Make a new, empty folder. Add a new file in it called app.py that contains the following code:

# app.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

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

Welcome to your web app! Run it with python app.py. You might need to pip install flask before this bad boy will run.

Your terminal will do…. something? Nothing? In order to see the real magic, visit http://localhost:5000. Or http://127.0.0.1:5000!

Tada! it’s a web server, sending out a web site, just like Amazon or Geocities or whatever, except it’s running on your computer and only you can see it.

Both localhost and 127.0.0.1 mean “your own computer,” and the 5000 is the port. If the IP address is the address of your computer in the world, the port is like a room number. If something is hanging out in room 8888 (Jupyter notebook!), no one else can stay in there.

Flask uses 5000 because it thinks hey, no reason not to. If something else was using 5000 Flask would panic and not work (there’s nowhere for it to stay, after all). You could change it by doing app.run(debug=True, port=5001) or whatever else you wanted, but for now let’s be satisfied with the basics.

It’s pretty boring, though, and it only works for one URL. If you tried to go to http://localhost:5000/shoelaces, you’d get a Not Found error, just like if you tried to visit a web page on the Internet that doesn’t work.

2.1.1 Servers up servers down

If you were paying attention to your Terminal, you might have noticed that every time you refresh your page, it prints out a new line.

127.0.0.1 - - [13/Jun/2019 19:19:15] "GET / HTTP/1.1" 200 
127.0.0.1 - - [13/Jun/2019 19:25:09] "GET /shoelaces HTTP/1.1" 404 

That’s Flask spitting out debugging information, just in case there’s an error. The 200 means everything went okay, while 404 means that it couldn’t find that page.

Go ahead and try to type something in that window, like a nice ls or pwd…. it won’t work! That’s because Python/Flask is busy being in charge of that command line now, and the program won’t stop running until you hold down the control key and press C, aka Ctrl+C.

Go ahead and Ctrl+C your way out of the Python app.

You’re back at the command line now! If you try to refresh your web site at http://localhost:5000/, you’ll also see it’s totally broken and doesn’t work at all now. That’s because your server is down!

Before we turn it back on, let’s make a little adjustment to our app.py. Let’s help it support that /shoelaces URL we were talking about before:

# app.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

@app.route("/shoelaces")
def shoelaces():
    return "This works now!"

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

Restart your server by running python app.py again, then visit http://localhost:5000/shoelaces again.

Hooray! Success!

2.1.2 Routing in Flask

The code we added looked like this:

@app.route("/shoelaces")
def shoelaces():
    return "This works now!"

This is called a route, it’s basically a URL where your web server has agreed to listen to. If you know about APIs, maybe you could call it an endpoint!

When someone visits /shoelaces, Flask runs the code underneath, and shows This works now! to whoever is on the page. If you’re confused by the @app or the def or any of that, don’t worry, it seriously doesn’t matter. There’s only one and a half rule:

When you add a new route, you add an app.route, but you also need to change the name of the def part.

When we added the /shoelaces route, we mostly re-used the code from above (the def and the return), but we renamed def hello to be def shoelaces. Let’s compare them:

@app.route("/")
def hello():
    return "Hello world!"
@app.route("/shoelaces")
def shoelaces():
    return "This works now!"

They both have different routes, and they both have different def names. Looks safe!

If you re-use one of those names, your app will break! So please try not to.

2.1.3 Here we go again

Try adding one more route, this one can be called /about. Mine is going to look like this:

@app.route("/about")
def about():
    return "All about my website!"

Visit http://localhost:5000/about, and voila! Perfect, simple, magic. You added a new route, you added a new page, you added a little bit of beauty to the internet.

Well, not the internet, actually! This web server only exists on your machine, and no one outside of your machine can access it. We’ll figure out how to put it online later, sorry if you were hyped to be the next MySpace.

2.2 Template time

I’m going to tell you a secret, if you promise to keep it to yourself: our web site sucks. Like, real bad. We’re barely going to break the top 100 in Alexa with this, so we’re going to have to do some bigtime fixing-up.

Right now our website can only say words. Let’s change our / route (our root) to say something else when you visit the page, someting that looks weird:

@app.route("/")
def hello():
    return "<h1>Do you like big text?</h1><p>I'm ambivalent but accepting</p>"

Visit http://localhost:5000/ again and be amazed.

Or not! If your web site stops working, don’t worry. Flask likes to quit runnning your server if you accidentally save Python code that has an error. Just check your command line, you probably just need to re-run python app.py.

2.2.1 Bringing structure to this world

What we did was add HTML to our web page. HTML is the language that web pages are made out of!

If you love pedantry, we’re about to hit a great fact: HTML is a language computers use, but it isn’t a programming language!

HTML is a markup language - it’s right there in the name, HyperText Markup Language - and it’s used to describe what the different elements on a page are. <h1> means “real important header” and <h2> means “less important header” and <p> means “paragraph” and so on and so forth.

You can add other web-friendly languages to make your pages fancier - CSS to make them pretty and JavaScript to make them interactive - but for the next uh ten seconds or so we’ll ignore that they exist and love our ugly ugly page.

The biggest problem at the moment is that we probably want to write more than just those two lines on our page. Maybe we want like ten lines on our page, right? Sixty lines? And if we do, it’s going to be a royal pain to type all that out in one single Python string.

Is there a solution, hiding somewhere out in the world? Of course there is! We’re going to move them into a different file.

Creat a new folder call templates. And another one called static, while we’re at it!

Put a new empty file called index.html in your templates folder. It can live an alone, empty life for a second, I promise it’ll improve in a bit.

Your folder structure should look like this:

app.py
static/
templates/
  index.html

2.2.2 Template time

Now we’re going to set up our route to use that template. First step, import a little function that will allow us to talk to the template. Edit app.py to add a new import to the top of the file:

# app.py
from flask import Flask
from flask import render_template

And now let’s use it - we’ll edit our / route again, but this time we’re going to point it to that index.html file.

@app.route("/")
def hello():
    return render_template("index.html")

Refresh http://localhost:5000/ and see your grand, beautiful page: ….it’s empty!

You if you check the command line running Flask, you’ll see that it’s printed 200, which means everything worked. We forgot one thing, though: adding content into our template!

Edit index.html to look like this:

<!doctype html>
<html>
  <head>
    <title>My incredible web site.</title>
  </head>
  <body>
    <h1>This is a REAL WEB PAGE.</h1>
    <h3>It's pretty cool.</h2>
    <p>I'm amazed and frankly you should be, too.</p>
  </body>
</html>

Refresh again!

Beautiful, beautiful, beautiful.

2.3 Adding CSS

It isn’t actually beautiful, but let’s not be too harsh on ourselves. We aren’t designers! We just have to take what the browser gives us and accept it as a cruel reality.

…or do we?

We aren’t designers, but luckily, other people are. And not only are the designers, but they’ve designed things and released them for us to use.

With one line of code we’re going to add their ways of styling a page to our amazing, beautiful website to make it even more amazing and beautiful.

2.3.1 Hello Bootstrap!

We’re going to be using Bootstrap, which is an incredibly popular and incredibly overwraught, heavyweight piece of overengineering. But like I said, it’s popular, so we don’t have any right to judge it (I guess?).

<!doctype html>
<html>
  <head>
    <title>My incredible web site.</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
  </head>
  <body>
    <h1>This is a REAL WEB PAGE.</h1>
    <h3>It's pretty cool.</h3>
    <p>I'm amazed and frankly you should be, too.</p>
  </body>
</html>

Okay, actually it isn’t that beautiful yet, our font just changed a bit. We need to give it a little nudge to beautify it…

<!doctype html>
<html>
  <head>
    <title>My incredible web site.</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
  </head>
  <body>
      <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <a class="navbar-brand" href="#">An incredible site</a>
      </nav>
      <div class="jumbotron">
        <div class="container">
          <h1 class="display-4">This is a <strong>real web page</strong>.</h1>
          <p class="lead">It's pretty cool.</p>
        </div>
      </div>
      <div class="container">
        <p>I'm amazed and frankly you should be, too.</p>
        <p>Look at this stuff!!! Incredible.</p>
      </div>
    </div>
  </body>
</html>

Okay, maybe more than a nudge, but that’s just how Bootstrap works: mostly well, and painfully. But you’ll get mostly used to it, I promise (or you’ll go use something nice like bulma instead).

2.3.2 What now?

Now that we have a somewhat cool website, we need some content to put on that site. Yeah, we could set up templates for about and shoelaces or whatever, but that’s a waste of time at the moment. We need some stuff!

So let’s take a break from the web and dance on over to database land, where we’ll learn to put together the database that’s going to power our site.