A Deep Dive into Flask Templates — SitePoint


In this article, we’ll take a deep dive into Flask templates, exploring their importance and benefits, and learning how to create and render templates, use template inheritance and layouts, work with template variables and control structures, handle forms and user input, work with built-in filters and custom filters, manage static files and media, and deploy advanced template techniques.

Table of Contents
  1. An Introduction to Flask Templates
  2. Creating and Rendering Templates
  3. Template Inheritance and Layouts
  4. Template Variables and Control Structures
  5. Template Context and Global Variables
  6. Template Forms and User Input
  7. Built-in Filters and Custom Filters
  8. Working with Static Files and Media
  9. Advanced Template Techniques
  10. Conclusion

An Introduction to Flask Templates

Flask is a popular Python micro web framework that provides powerful tools for building dynamic web applications. One of the key features of Flask is its powerful templating engine, which enables us to separate the presentation logic from the application logic in our web applications.

Flask templates are built on the Jinja2 template engine. They enable us to create dynamic and interactive web pages by combining HTML with Python code.

By the end of this article, you’ll have a comprehensive understanding of Flask templates, and you’ll be equipped with the knowledge to create dynamic and visually appealing web applications using Flask. Whether you’re a beginner or an experienced Flask developer, this deep dive into Flask templates will enhance your understanding and proficiency in building web interfaces.

Note: this is an advanced article on Flask, so to get the most out of it you’ll need to have a basic understanding of how Flask works. To get up to speed with the basics of Flask, check out this introduction to Flask.

Why are Templates Important in Flask?

Templates are key in Flask, as they promote code organization, maintainability, and reusability. By separating the presentation logic from the business logic, templates make it easier to manage and update a user interface without modifying the underlying application code. This separation improves collaboration between developers and designers, allowing each team to work on different aspects of the application independently.

Some of the benefits of using templates in Flask are laid out below.

Code Reusability. Templates enable us to define reusable components, such as headers, footers, navigation bars, and other components that can be included on multiple pages. This promotes a consistent user interface across the application and saves us from duplication.

Improved Readability. The separation of HTML code from the Python code leaves us with clean code, making it easy to read and understand.

Ease of maintenance. Building on improved readability, having code separated makes it easy for us to maintain. We can update the business logic without touching the template or presentation code, or we can update the templates without touching the Python code.

Flexibility. Using templates in Flask makes it easy to pass data to and from templates, allowing our application to create dynamic content. This gives our application the flexibility to handle different types of needs for different users.

Creating and Rendering Templates

Building on the philosophy of simplicity in Flask, working with templates is generally straightforward. One important requirement is that templates in Flask have to reside in a directory named templates, and this directory must be located in the same directory as our application file.

Here’s an example of an application structure:

my_app/
├── app.py
└── templates/
  └── index.html

The code block above is a plain-text representation of how our application could be structured. It shows a Flask project named my_app, which has an app.py file that will contain the application logic, and a templates directory that contains an index.html file. Structuring the application this way ensures that our business logic (Python code) is separated from the presentation logic (templates).

Since Flask uses the Jinja2 templating engine, it can render files in various extensions such as .svg, .html, .csv. However, for this article, we’ll use the .html extension, since all of the files we’ll be working with and rendering are HTML documents.

Let’s then create a template named index.html and place it in the templates directory:


DOCTYPE html>
<html>
  <head>
      <title>Indextitle>
  head>
  <body>
      <h1>Welcomeh1>
      <p>This is the index page.p>
  body>
html>

This is a basic HTML template: it has a head and body section. To render templates in Flask, the flask module has the render_template() method, which takes in the name of the template file as its first argument and also takes in optional keyword arguments representing the data that we may want to pass to the template.

Here’s an example:


from flask import Flask, render_template

app = Flask(__name__)

@app.route("https://www.sitepoint.com/")
def index():
  return render_template('index.html')

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

In the Flask application above, we import Flask and render_template() from the flask module. The Flask class helps us create the Flask application instance. The render_template() will render and return the index.html template.

index() is the view function that will handle requests from the root URL. In this example, this function will just return the template rendered by the render_template() function.

So, in summary, we create a template, place it in the templates directory, and then use the render_template() function to return the template to the user.

Template Inheritance and Layouts

Inheritance in object-oriented programming is a concept that enables classes to inherit or acquire the properties and behaviors of another class. Inheritance in the context of templates in Flask is a feature provided by Flask and the Jinja2 templating engine that enables us to define a base template and child templates.

Template inheritance works by creating a base template that contains the common elements and structure of our web pages. This base template serves as a blueprint that can be extended and customized by the individual child templates. The child templates inherit the structure and content of the base template and can override specific blocks to provide unique content for each page.

Creating a base template

To set up template inheritance, we start by creating a base template. It will contain the common HTML structure and elements. Typically, it will include the section, the navigation menu, the footer, and any other elements that might be shared across the various pages of the web application.

Here’s an example of a base template named base.html:


DOCTYPE html>
<html>
  <head>
        <title>{% block title %}{% endblock %}title>
  head>
  <body>
      <nav>
            
      nav>
      <div class="content">
            {% block content %}{% endblock %}
      div>
      <footer>
            
      footer>
  body>
html>

This example shows an HTML document. It includes some tags such as {% block %}. The block tags are important in template inheritance, since they indicate all the code that the child template can override. A block tag will usually have a descriptive name that indicates the kind of content the block expects. It’s marked by an opening and a closing block. So the base.html template has two blocks: the title and the content block. Any child template that inherits this template is able to provide its own specific content for the two blocks.

Extending the base template in child templates

Extending (inheriting) a base template is generally straightforward. To show that a template is inheriting from a particular template, we use the {% extends %} tag, followed by the path to the template we’re inheriting. Once we’ve indicated the template we’re extending, we can go ahead and override the blocks defined in the parent template.

Here’s an example of a child template named home.html that extends the base.html template:


{% extends 'base.html' %}

{% block title %}Home - My Website{% endblock %}

{% block content %}
  <h1>Welcome to My Websiteh1>
  <p>This is the home page content.p>
{% endblock %}

In the example above, the first statement is the extends tag ({% extends ‘base.html’ %}). This statement tells Flask that the home.html template extends the base.html template. The {% block title %} and {% block content %} tags override the corresponding blocks in the base template, providing specific content for the home page.

To override any of the blocks provided in the base.html template, the child template has to provide its own specific content. As we can see, the home.html template provides its own content for the two blocks, so when it’s rendered on the page it will show the content provided on its own pages.

Overall, using template inheritance in our projects enables us to reuse code. It also enables us to define content that can be used across the different pages, giving our projects a consistent look. At the same time, it gives us the room to define page-specific content by overriding blocks in the child templates.

Template Variables and Control Structures

To be able to create dynamic applications, we need the ability to pass data to templates from our Python application. To pass variables from a Flask view function to a template, we can include them as arguments when calling the render_template() function as key–value pairs, or in a context dictionary. The key–value pairs represent the variable name in the template, while the value is the actual value of the variable.

Here’s an example of passing variables as key=value pairs:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("https://www.sitepoint.com/")
def index():
  name = "Antony"
  age = 30
  return render_template('index.html', name=name, age=age)

In the example above, we have an index() function that declares two variables — name and age — which are passed to the template as optional arguments to the render_template() function.

Here’s an example of how we could pass variables as context dictionaries to the template:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("https://www.sitepoint.com/")
def index():
  name = "John"
  age = 25
  context = {
      'name': name,
      'age': age
  }
  return render_template('index.html', **context)

The example above is similar to the first one in terms of functionality. However, in this example, we create a context dictionary named context, which contains key–value pairs of our variables name and age. Then we pass the information to the render_template() function, with the template name index.html as the first argument and the context dictionary as the second argument. However, we’ll use **context notation to unpack the context dictionary.

Once we pass variables to a template, we can access them using the {{ variable_name }} syntax on the template. Variables can represent any type of data, such as strings, numbers, lists, or even more complex objects.

To access the variables in the template, we’ll use their names as specified in the context dictionary, or in the first case, where we pass them as key–value pairs.

Here’s an example where we retrieve the name and age variables:

DOCTYPE html>
<html>
<head>
  <title>My Websitetitle>
head>
<body>
  <h1>Hello, {{ name }}!h1>
  <p>You are {{ age }} years old.p>
body>
html>

In this example, we have the {{ name }} and {{ age }} placeholders, which are replaced by the actual values passed from the view function. Passing variables using a context dictionary lets us keep our render_template() function cleaner by not passing all the variables one by one.

In the next section, let’s look at how we could use the various Python control structures in the templates to display and work with data.

Using control structures in templates

Control structures in programming are constructs that determine the order in which code blocks are executed based on certain conditions. They allow us to control the execution of a program by specifying the sequence and conditions under which different actions should be performed. In Flask templates, we can use Python control structures like conditionals (if, else, if) or iteration control structures (for, while).

Using these control structures, we’re able to work with different kinds of data and therefore have pages that are more dynamic. We’ll next look at how we could use the various kinds of control structures in our templates.

Conditionals (if, else, elif)

Conditional statements enable our web application to take different paths or perform different actions depending on whether a condition evaluates to true or false. The {% if %}, {% else %}, and{% elif %} tags are used for conditionals. Using conditional statements, we can display certain data or work on it to give a different outcome depending on different conditions.

Here’s an example:

{% if temperature > 30 %}
  <p>It's a hot day!p>
{% elif temperature > 20 %}
  <p>It's a pleasant day.p>
{% else %}
  <p>It's a cold day!p>
{% endif %}

In the example above, we have a temperature variable that holds the temperature value. The template will conditionally display a message depending on the value held in the temperature variable.

We could combine the conditionals with logical operators (and, or, not) or comparison operators (==, <, >, etc.) to create more complex conditional statements in our templates, extending the capability of our application.

Loops (for, while)

Using loops, we can iterate over a sequence of elements or repeat a section of code until a condition is met.
The {% for %} loop is used to iterate over a sequence such as a list or a dictionary.

Here’s an example:

<ul>
  {% for item in my_list %}
  <li>{{ item }}li>
  {% endfor %}
ul>

In the example above, we have a list named my_list. We use the for loop to iterate over it to get the individual items (item) and then display them using a list item.

The {% while %} loop is used to repeat a section of code until a condition becomes false or true. Here’s an example where we iterate over a counter that’s set at zero until the value becomes five and then the while condition becomes false and the while loop exits:

{% set counter = 0 %}
{% while counter < 5 %}
  <p>Iteration {{ counter + 1 }}p>
  {% set counter = counter + 1 %}
{% endwhile %}

Using variables and control structures in Flask templates, we’re able to handle dynamic data, apply conditional logic, and iterate over sequences. These features give us the flexibility to create dynamic and interactive web pages.

Template Context and Global Variables

Template context refers to the set of variables and values available to the template when it’s rendered. The template context provides the necessary data needed by the template to dynamically generate the template’s HTML content.

Understanding template context

The template context is available when rendering a template using the render_template() function. The function enables us to pass variables from our view functions to the template for display or processing.
By default, Flask provides the following variables to the template context:

  • request: contains information about the current request so that we can access the incoming request data, though it will be unavailable if a template is rendered without an active request context

  • session: gives us session information, enabling us to remember information from one request to another

  • config: contains configuration information about our application

  • url_for(): a function (used to generate dynamic URLs) for routes within our application

  • g: enables us to set global variables that are accessible throughout the application

Using global variables in templates

There are times when we may want to pass the same information or some shared state around in our application and have it remain consistent throughout the lifespan of one active request. For this purpose, Flask provides the global namespace object (g), which can be used to store and access global variables.

To use a global variable in a template, we need to assign the value to the g object in a view function.

Here’s an example where we share the title of the site globally:

from flask import Flask, render_template, g

app = Flask(__name__)

@app.before_request
def set_global_variables():
  g.site_title = "My Website"

@app.route("https://www.sitepoint.com/")
def index():
  return render_template('index.html')

To use the g object, we have to import it from the Flask module, and since we want the title variable to be accessible to every request, we use the before_request decorator. This means that the variable will always be set before every request comes into our application. We then create a custom function named set_global_variables(), where we set the variables that we want to have access to globally in our application.

To access the variables in the templates, we have to use the {{ g.name_of_the_variable }} notation.

Here’s an example:

DOCTYPE html>
<html>
<head>
  <title>{{ g.site_title }}title>
head>
html>

By using global variables in templates, we can store and access data that’s shared across multiple views without the need to pass them explicitly from each view function.

Template Forms and User Input

Forms are important on the Web. They present a way of taking input from users that can be saved or processed. Flask provides features and tools for handling forms, building form interfaces in templates, validating and processing form data, and displaying form errors.

Building forms in templates

Flask provides two main ways of building forms: we can build them entirely using HTML, or we can use Flask-specific form helpers to generate form elements like buttons, labels, and form fields. For instance, Flask couples well with the WTForms library to provide more functionality and flexibility for building forms.
When we combine any of the two methods with control structures and template variables, we can dynamically populate form fields, and set default values, creating very intuitive forms.

Let’s see examples of how we can build forms in Flask using both methods.

Building a form using HTML

To create a form in templates, we can use HTML

tags along with various input elements such as ,