Templates are static HTML files that contain placeholders for dynamic data. During template rendering, the dynamic data placeholders are replaced with the actual values and passed to a rendering method. In this topic, we’ll learn how to use templates in Flask.
Templates in Flask
To start working with templates in Flask, let's create a folder structure like the one below:
|-----Application/
|---templates/
| |---welcome.html
|---app.py
Flask requires developers to store all templates in a templates folder. This folder stores all html templates that are going to be used within the project. For now, it contains the only HTML file: welcome.html
<!doctype html>
<html>
<body>
<h1>Hello world!</h1>
</body>
</html>
App.py contains the code of our Flask app. It should look as follows:
#______________app.py______________________
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_name():
return render_template('welcome.html')
if __name__ == '__main__':
app.run(debug=True)
This is the basic way to run a Flask server. You know how to do it. The new feature here is that it renders and returns the welcome.html file. In the previous topics, we've implemented the HTML output right in the view function and then returned it as a string. That approach is fine for testing or learning; for real-world issues, it would be better to render templates from .html files. There are a few reasons for this:
- It's bad practice to overload view methods with multi-line strings;
- A longer HTML output string takes more time to read and update, particularly when you pass variables to it;
- Templates are easy to replicate; you can take them from one specific place instead of copying and pasting them every time;
- Template rendering supports automatic data type conversion and several helpful statements (we will cover them in the following topics).
Getting back to our example, render_template() generates output from the specified template file from the templates folder.
render_template() function.
When we input http://127.0.0.1:5000/ in our web browser, we'll see Hello world!
Jinja2
Jinja2 is a fast, expressive, and extensible templating engine in Flask. Jinja can help you incorporate dynamic data into static templates. We can do it with special placeholders that allow Python-like syntax. This template is then rendered with the render_template() function; the one that's already familiar to you. The dynamic data we want to specify is passed to this function as an argument. The Jinja2 template engine uses the following delimiters for escaping in HTML:
-
{% ... %}: conditional and looping statements likeif,forare enclosed within a string that starts a block{%and one that ends it%}. -
{{ ... }}: variables are enclosed within variables that start{{and end}}a string. With their help, the value of a variable can be printed to the template output.
These are the main Jinja2 tools we'll need for now.
Passing a variable to the template
If you want your template to interact with a variable, use the Jinja2 syntax {{ ... }} to embed a value of a variable in the template file. Let's update the welcome.html:
<!doctype html>
<html>
<body>
<h1>Hello {{ name }}!</h1>
</body>
</html>
To pass this variable to the template, we need to specify it as a parameter of the render_template() function. Update the hello_name() function as follows:
@app.route('/hello/<user>')
def hello_name(user):
return render_template('welcome.html', name=user)
The route in the decorator has changed, hello_name() now takes an argument, and the render_template() function receives the second argument. When we input http://127.0.0.1:5000/hello/Jack, we will pass the string Jack to the user variable, and then the user variable is passed along with render_template(). Finally, the render_template() function embeds the variable that contains the string Jack in the welcome.html template. The final output will look like this:
Passing a dictionary and an array to the template
Apart from variables, we may want to pass a list or a dictionary to a template. Similar to variables, we need to modify two things: the welcome.html template and the hello_name() function.
Let's start with the function. We need to pass a list and dictionary as parameters to render_template():
@app.route('/')
def hello_name():
arr = [1, 2, 3] # array
di = {"Jan": 1, "Feb": 2, "March": 3} # dictionary
return render_template('welcome.html', arr=arr, di=di)
On the template side, we again refer to the {{ ... }} syntax and embed each element's value in the template file. Let's change the welcome.html:
<!doctype html>
<html>
<body>
<h2>Array Output</h2>
<h3>{{ arr[0] }} </h3>
<h3>{{ arr[1] }} </h3>
<h3>{{ arr[2] }} </h3>
<h2>Dictionary Output</h2>
<h3> Jan - {{ di["Jan"] }} </h3>
<h3> Feb - {{ di["Feb"] }} </h3>
<h3> March - {{ di["March"] }} </h3>
</body>
</html>
As you can see, the syntax is similar to Python. Now, when we go to http://127.0.0.1:5000/, we'll see the following:
While rendering the template, the array and dictionary were processed correctly. We've passed the array arr=[1, 2, 3] and dictionary di={"Jan": 1, "Feb": 2, "March": 3} along with their values.
Conclusion
In this topic, we've learned how the Jinja2 template language can help us with rendering templates in Flask applications. We've also learned the pros of this approach and how to process simple data types in the template. We’ll dive a bit more into rendering templates with Jinja in the following topics.