21.4. Routes

Routing manages the flow of data within a network. For example, when a server receives a form request, it needs to know where to send the information and how to handle the response. Proper routing helps control this process.

In the case of Flask applications, different HTTP requests trigger different functions in the Python program. Let’s take a closer look at how this works with http://127.0.0.1:5000 and @app.route('/').

21.4.1. Server IP Address

When we launch a Flask application, it starts a server on our machine. This server gets its own IP address: 127.0.0.1, which is actually the address of our computer.

Network servers listen for HTTP connections on a specific port. To keep things simple, Flask defaults to a port that is freely available on our machine (5000 in this case). Other ports can be used, but they may require passwords or other security features. For this course, we won’t change the default setting.

Note

If you need a quick review, we broke down the different parts of a web address in the HTTP chapter.

When we open a tab in our browser and enter the address http://127.0.0.1:5000, we send a GET request to the Flask server. When the server receives that request, our Python program jumps into action. The hello() function runs and returns a string. The return statement in the function is the response to the GET request. Flask sends the response from its server to our browser. This generates the content we see on the page (e.g. Hello, Flask!).

The request/response flow between the local client and server.

The request/response cycle between the browser and Flask server.

How does Flask know what data to send back from the server? This is why we include the @app.route() decorator. The argument inside the parentheses corresponds to a specific URL. When the sever receives a request with that web address, it runs the function immediately below the decorator. In our simple Flask application, this is the hello() function.

Note

We use @app.route('/') in our code instead of @app.route('127.0.0.1:5000'). The / symbol is an abbreviation. It stands for the address of the server. Even if the IP address for the server changes, Flask will automatically use the proper URL.

21.4.2. Paths

As mentioned before, the @app.route() decorator links a specific URL to one Python function. The best way to see what this means is to do some live coding.

Try It!

  1. If your hello.py program is not currently running, launch it again from the terminal. Make sure you see the most recent content in your browser.

    A page with an h1 heading and a "New Number" button.

    Where we left off on the last page.

  2. In the address bar, change the URL to http://127.0.0.1:5000/hello and tap Enter. Note the Not Found error that appears. The message explains that the URL you entered isn’t recognized by the server.

    Not Found: The URL in the address bar is not recognized by the server.
  3. In hello.py, change the decorator as follows:

    7
    @app.route('/hello')
    
  4. Save the code, then refresh the page in your browser. Properly done, you should once again see the heading and button.

Let’s think about what just happened.

Recall that URLs can include a path as part of the address. The path consists of one or more names separated by /. The URL http://127.0.0.1:5000/hello includes the IP address for the server AND a path to follow.

When you entered http://127.0.0.1:5000/hello in the address bar, you sent a different GET request to the server. You still asked for data, but this time you told the server to look inside a directory called hello.

The decorator @app.route('/') tells Flask, When a GET request comes for 127.0.0.1:5000, run the hello() function. However, there is nothing in the Python code that recognizes the address 127.0.0.1:5000/hello. When the server receives that request, Flask scans the Python program for a matching decorator. Since it doesn’t find one, it returns the Not Found error message.

By changing @app.route('/') to @app.route('/hello'), we fixed the mismatch. However, this came with a cost.

Try It!

Return to your browser and enter http://127.0.0.1:5000 in the address bar. What happens?

Navigating to http://127.0.0.1:5000 triggers the @app.route('/') decorator. Unfortunately, we removed that reference when we replaced '/' with '/hello'.

This might sound like a picky syntax, but it is actually quite useful. It lets us tie specific HTTP requests to specific actions. By adding more routes to the Python code, we can make our program respond to more than one URL.

21.4.3. Add a Second Page

Take a moment to run through the usual git status/add/commit sequence. Next, use git checkout -b to create a new branch in the repository.

In the new branch, our code looks something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from flask import Flask
import random

app = Flask(__name__)
app.config['DEBUG'] = True

@app.route('/hello')
def hello():
   page = """
      <h1>Here's a random number: {0}</h1>
      <form>
         <button>New Number</button>
      </form>
   """
   num = random.randint(1, 25)
   return page.format(num)

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

The hello() function runs only when the server receives a request with the /hello path at the end of the URL. However, we can easily assign more than one address to the same function.

Try It!

  1. Add the @app.route('/') decorator before the hello() function:

     7
     8
     9
    10
    @app.route('/')
    @app.route('/hello')
    def hello():
       # Function code here...
    
  2. Save the code, then launch the program.

  3. Confirm that http://127.0.0.1:5000 and http://127.0.0.1:5000/hello produce no errors when entered in the address bar.

Key idea: Multiple URLs can trigger the same Python function.

Now let’s add another function to our Python code.

Try It!

  1. Open up some space between the hello() function and the app.run() conditional.

  2. Add this new decorator and function:

    17
    18
    19
    20
    21
    22
    23
    @app.route('/goodbye')
    def goodbye():
       message = "<h2>This is the second page!</h2>"
       return message
    
    if __name__ == '__main__':
       app.run()
    
  3. Save the code, then refresh the page in the browser.

  4. Type http://127.0.0.1:5000/goodbye into the address bar. Do you see the new message?

  5. Verify that http://127.0.0.1:5000 and http://127.0.0.1:5000/hello show the original content.

Key idea: We can control a multi-page website by adding different functions and routes to the Python program.

Nice! We just created a two-page website that responds to three different URLs. We can switch between the pages in our project by changing the URL in the address bar. Right now, we have to do this manually. However, we will soon learn a better way to flip between pages.

21.4.4. More Practice

Note

Remember that the server and your application are both running locally. Only you can see your live webpage.

  1. First, save and commit your work.

  2. Code a third function in hello.py. It should return a different string compared to the hello() and goodbye() functions.

  3. Add the @app.route('/third_page') decorator before your new function.

  4. Save the code, then refresh the page in your browser. Enter http://127.0.0.1:5000/third_page in the address bar to make sure your changes work.

  5. Flip between the three pages in your website by changing the URL.

Tip

You will often see that the argument inside @app.route() matches the name of the function below it (e.g. @app.route('/hello') placed just above def hello():).

Matching the path and function names is NOT required, but doing so helps you organize your code. For example, looking at the path in a URL tells you which function controls its content.

21.4.5. Check Your Understanding

Question

Assume we modify the functions in our program:

 7
 8
 9
10
11
12
13
14
15
16
17
@app.route('/hi')
def hi():
   return "Hi!"

@app.route('/hi/status')
def status():
   return "How are you?"

@app.route('/hi/status/bye')
def bye():
   return "Bye!"

In the browser, we enter the URL http://127.0.0.1:5000/hi/status/bye. Which function will run in response?

  1. hi()
  2. status()
  3. bye()
  4. None of them.
  5. All of them.