1. Basics¶
In this tutorial, we’re going to develop an application for managing a movie collection. We’ll start by creating a simple home page containing only a title. Then, we’ll add a greeting message based on the current date to show how dynamic content is generated. Next, we’ll create another page, again containing only a title. This second page will be populated with the list of movies in later chapters. Finally, we’ll provide a link from the home page to the movie list page. In the end, the home page will look as shown in Fig. 1.1.
1.1. Applications¶
Using Flask, we can create a web application in just one source file.
In Listing 1.1, you can see the code for a very simple
application that serves only one page with only a title in it. Save this code
in a file named server.py
and run it using the command:
python server.py
Now, when you visit the address http://localhost:8080/
you should see
the title.
1 2 3 4 5 6 7 8 9 10 11 12 13 | from flask import Flask
app = Flask(__name__)
@app.route("/")
def home_page():
return "My movie collection"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
|
Let’s go over this code line by line:
Line 1: The
Flask
application class gets imported. Applications are instances of this class.Line 4: An application of this class gets instantiated.
Line 13: The application gets started. The
host
parameter specifies that the server should be publicly available, and theport
parameter specifies that it should run on port 8080. We also set the application to run in debug mode to get better feedback about errors.Warning
Debug mode causes security problems. Therefore this mode should be enabled only during development.
Lines 7-9: A view function is defined to handle requests to the home page. It simply returns a string containing the title. The
route
decorator registers the/
route with this function. So whenever there is a request to the/
route, this function will be invoked and its result will be sent back to the client as the response.
Note that the string returned by the view function is not an HTML page, but only a string. We could return an HTML page as in:
return """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My movies</title>
</head>
<body>
<h1>My movie collection</h1>
</body>
</html>
"""
But this would not only make the code less readable, it would also be very
difficult to maintain. The proper way to handle this is to use a template
that contains the HTML markup. By default, Flask looks for template files
in the templates
folder; so we create a file named home.html
in that folder to contain the home page template given
in Listing 1.2.
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My movies - Home</title>
<link rel="stylesheet" href="/static/mymovies.css"/>
</head>
<body>
<h1>My movie collection</h1>
</body>
</html>
|
Now, as shown in Listing 1.3, we can import a function for rendering a template (line 1), and the view function can call it to render the home page (line 9).
1 2 3 4 5 6 7 8 9 10 11 12 13 | from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home_page():
return render_template("home.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
|
Static files like images and style sheets are placed into the static
folder. Our template (Listing 1.2) contains a style sheet
reference on line 6. To make this reference work, we create the file
static/mymovies.css
with the contents given
in Listing 1.4.
1 2 3 | h1 {
color: #e9601a;
}
|
1.2. Dynamic Content¶
Let’s add a greeting message to our home page based on the current date. We first change our template to add the necessary markup (Listing 1.5, line 10).
1 2 3 4 5 6 7 8 9 10 11 12 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My movies - Home</title>
<link rel="stylesheet" href="/static/mymovies.css"/>
</head>
<body>
<h1>My movie collection</h1>
<p>Have a nice {{ day }}!</p>
</body>
</html>
|
Since the name of the current day will change between different visits, we need our template system to be able to generate the HTML output dynamically. For this purpose, we’re going to use Jinja, which is the default template system used by Flask.
In Jinja templates, the parts marked with {{
and }}
will be replaced
by the value of the expression they contain. The parameters in the expression
have to be supplied by the view function that renders this template.
In our example, the home_page
function has to send a value for day
as a parameter. Listing 1.6 shows how the view function decides
the name of the current day (lines 11-12), and sends it to the template
(line 13).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from datetime import datetime
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home_page():
today = datetime.today()
day_name = today.strftime("%A")
return render_template("home.html", day=day_name)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
|
The application, as implemented so far, runs as follows:
- An application object gets instantiated.
- The application registers the
home_page
function to respond to requests for the/
route. - The application starts running on the localhost on port 8080 and waits for requests.
- When a request comes for
http://localhost:8080/
, thehome_page
function gets invoked. - This function gets the current day and renders the home page template, passing the name of the day as a parameter to it. The server sends the rendered page back to the client.
- The client parses the response and encounters the link for the style sheet.
It makes a request to
http://localhost:8080/static/mymovies.css
. - The server sends back the
mymovies.css
file.
1.3. Adding Links¶
Now we want to create a second page which will be used for listing the movies in the collection. At first, the page will only contain some static text; it will be populated in later chapters. The template for the page is given in Listing 1.7.
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My movies - Movie list</title>
<link rel="stylesheet" href="/static/mymovies.css"/>
</head>
<body>
<h1>Movies</h1>
</body>
</html>
|
Our application needs a view function to respond to requests for this page.
We register the movies_page
function to handle the /movies
route
(Listing 1.8, lines 16-18).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from datetime import datetime
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home_page():
today = datetime.today()
day_name = today.strftime("%A")
return render_template("home.html", day=day_name)
@app.route("/movies")
def movies_page():
return render_template("movies.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
|
Our last step will be to provide a link from the home page to the movie list page. To achieve this, we just have to modify the home page template (Listing 1.9, lines 12-14).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My movies - Home</title>
<link rel="stylesheet" href="/static/mymovies.css"/>
</head>
<body>
<h1>My movie collection</h1>
<p>Have a nice {{ day }}!</p>
<ul>
<li><a href="/movies">List movies</a></li>
</ul>
</body>
</html>
|
Exercise 1
Add a link from the movie list page to the home page. (Solution)