Using Flask Templates
Writing HTML in Python code is not a good practice. It is hard to maintain, understand and becomes really difficult with larger pages. Flask provides a way to write HTML in separate files and then use them in the Python code. These files are called templates which are built using Jinja2.
Jinja2 Templates
Templates are special HTML files that contain placeholders for dynamic content. These placeholders are replaced with actual values when the template is rendered. Templates are used to separate the presentation logic from the business logic.
Flask stores all of its templates in a folder called templates
. This folder should be created in the same directory as the app.py
file.
- app.py
Directorytemplates/
- index.html
Creating a Template
<!DOCTYPE html><html lang="en"> <head> <title>{{ title }}</title> </head>
<body> <h1>{{ heading }}</h1> <p>{{ content }}</p> </body></html>
-
The template is based on an HTML file so requires the standard HTML structure.
-
Each part that would contain content is instead replaced by a placeholder enclosed in double curly braces
{{ }}
. These placeholders are replaced with actual values when the template is rendered.
Rendering a Template
To render a template, we need to use the render_template
function from the flask
module. This function takes the name of the template file and the values to be replaced in the placeholders.
from flask import Flask from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')def home(): return "<h1>Welcome to the home page!</h1>" return render_template('index.html', title='Home', heading='Welcome to the website', content='This is a simple website built using Flask')
When we run the server and visit the home page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>Home</title> </head>
<body> <h1>Welcome to the website</h1> <p>This is a simple website built using Flask</p> </body></html>
Complex Templates
Templates can be as complex as you want with lots of different functionality.
Base Template
Base templates can be used so you don’t have to repeat the same code in every template. Create a new file called base.html
in the templates
folder.
<!DOCTYPE html><html lang="en"> <head> <title>{% block title %}{% endblock %}</title> </head>
<body> {% block content %}{% endblock %} </body></html>
-
The
base.html
file contains the basic structure of an HTML file. -
The
title
andcontent
sections are enclosed in{% block %}
tags. These are placeholders that can be overridden in the child templates.Instead of putting content from a variable inside of these tags they will instead be filled with a block of content from the child template. Instead of using
{{ variable_name }}
we use{% block block_name %}{% endblock %}
which indicates it is a block instead of a variable. -
As these are blocks, they can be overridden in the child templates by using the same block name.
They are overridden by using the
{% block %}
tag with the same name as the block in the parent template.
We will then need to update our index.html
file to extend the base.html
file.
<!DOCTYPE html><html lang="en">{% extends 'base.html' %} <head> <title>{{ title }}</title>{% block title %}{{ title }}{% endblock %} </head>
<body> <h1>{{ heading }}</h1> <p>{{ content }}</p>{% block content %} <h1>{{ heading }}</h1> <p>{{ content }}</p>{% endblock %} </body></html>
This would give a index.html
that now looks like this:
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %} <h1>Welcome to the website</h1> <p>This is a simple website built using Flask</p>{% endblock %}
-
Using
{% extends 'base.html' %}
we indicate that theindex.html
file extends thebase.html
file. This means that the content of theindex.html
file will be inserted into thebase.html
file. -
We then use
{% block title %}Home{% endblock %}
to override thetitle
block in thebase.html
file. -
We then use
{% block content %}...{% endblock %}
to override thecontent
block in thebase.html
file.
When we run the server and visit the home page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>Home</title> </head>
<body> <h1>Welcome to the website</h1> <p>This is a simple website built using Flask</p> </body></html>
Includes
Includes can be used to include a file in another file. Create a new file called header.html
in the templates
folder.
<header> <h1>Home</h1></header>
We will then need to update our base.html
file to include the header.html
file.
<body> {% include 'header.html' %} {% block content %}{% endblock %} </body></html>
When we run the server and visit the home page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>Home</title> </head>
<body> <header> <h1>Home</h1> </header> <h1>Welcome to the website</h1> <p>This is a simple website built using Flask</p> </body></html>
Passing Variables to Templates
If you want to pass variables to the included file, you can do so by passing the variables as arguments to the include
function. We can modify our header.html
file to accept a title
variable.
<header> <h1>Home</h1> <h1>{{ title }}</h1></header>
We will then need to update our base.html
file to include the header.html
file with the title
variable.
<body> {% include 'header.html' %} {% include 'header.html' with title={{ title }} %} {% block content %}{% endblock %} </body>
When we run the server and visit the home page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>Home</title> </head>
<body> <header> <h1>Home</h1> </header> <h1>Welcome to the website</h1> <p>This is a simple website built using Flask</p> </body></html>
Loops
If we have a list of items that we want to display, we can use a loop to iterate over the list and display each item. Create a new file called list.html
in the templates
folder.
{% extends 'base.html' %}
{% block title %}List{% endblock %}
{% block content %} <h1>List of items</h1> <ul> {% for item in items %} <li>{{ item }}</li> {% endfor %} </ul>{% endblock %}
We will then need to update our app.py
file to render the list.html
file.
@app.route('/list')def list(): items = ['Item 1', 'Item 2', 'Item 3'] return render_template('index.html', title='List', heading='List of items', content='This is a list of items', items=items)
When we run the server and visit the list page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>List</title> </head>
<body> <h1>List of items</h1> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </body></html>
Conditionals
If we want to display content based on a condition, we can use conditionals. Create a new file called conditional.html
in the templates
folder.
{% extends 'base.html' %}
{% block title %}Conditional{% endblock %}
{% block content %} <h1>Conditional content</h1> {% if condition %} <p>Condition is true</p> {% else %} <p>Condition is false</p> {% endif %}{% endblock %}
We will then need to update our app.py
file to render the conditional.html
file.
@app.route('/conditional')def conditional(): condition = True return render_template('conditional.html', title='Conditional', heading='Conditional content', content='This is a conditional content', condition=condition)
When we run the server and visit the conditional page, we will see the content from the template file.
<!DOCTYPE html><html lang="en"> <head> <title>Conditional</title> </head>
<body> <h1>Conditional content</h1> <p>Condition is true</p> </body></html>