Jinja 2 in Flask 3

- Andrés Cruz

En español
Jinja 2 in Flask 3

One of the problems we currently have is that we do not have an effective way to present the data to the end user. Since Flask is a web technology, the usual thing is to present this data on a web page; this is where what is known as the template engine becomes important; a template engine is a resource used to present this data from the server and generate a web page in the process, they are the next layer of the MVC that corresponds to the view and allows the presentation logic to be separated from the data; to do this, a set of features are used to manipulate the server data and generate the HTML page that will be consumed by the user. Features such as impressions, filters, conditionals, cycles or imports allow generating this HTML code necessary to represent a page. Web. They are widely used in server-side programming, since they allow the presentation of data without having to modify the source code.

In short, with a template engine it is possible to present the data managed by the server, specifically in our case in Flask and generate the HTML in the process; for example, if we have a list of users, we can print it to a table or similar in HTML using certain functionalities (directives).

About Jinja

Jinja is a templating engine written in Python designed to be simple and expressive; Jinja is a templating engine that can be used in other frameworks such as FastAPI, it is also very similar to the one used by Django.

With Jinja as a template engine we can easily render the API responses.

The Jinja templating engine uses square brackets { } to distinguish its expressions and syntax from HTML:

  1. The {{ }} syntax is called a variable block and we can use it to print to the template.
  2. The {% %} syntax houses control structures such as if/else, loops, and macros.
  3. The {# #} syntax is for comments.

Set up Jinja in Flask

By default, Flask looks for the templates folder named templates at the root level of the application. If this folder is present, Flask will automatically read the contents making the contents of this folder available for use with the render_template() method from the controllers; so, we will create the folder mentioned above:

app\my_app\templates

Let's start by creating a basic HTML page, which would be a template in Jinja:

my_app\templates\index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Page</title>
</head>

<body>
    <h1>Hello Flask</h1>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Reiciendis libero possimus nihil ipsam quam deleniti
        voluptas eaque qui. Necessitatibus corporis quas odio tenetur quos, recusandae itaque doloremque assumenda
        consequatur aliquam.</p>
</body>

</html>

From a controller, we return the template instead of text as we had before:

my_app\__init__.py

from flask import render_template, request 

@app.route('/') 
@app.route('/hello') 
def hello_world(): 
    return render_template('index.html') 

Let's make some specific changes so that we can understand the potential of Jinja in conjunction with server-side frameworks like Flask, which is to dynamically pass data from Flask to then consume and print from the view; for it:

my_app\__init__.py

from flask import render_template, request 

@app.route('/') 
@app.route('/hello') 
def hello_world(): 
    name = request.args.get('name', 'DesarrolloLibre') 
    return render_template('index.html', name=name)

With:

request.args.get('name', 'DesarrolloLibre') 

A parameter is obtained via GET called "name"; The parameter is then supplied to the template by:

name=name

Where:

name=name

It is the variable called name:

name=name

Indicates the way to access the name variable in the controller from the view:

name=name

From the template or view, we print by referencing the variable from the view with double curly braces:

my_app\templates\index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Page</title>
</head>

<body>
    <h1>Hello {{name}}</h1>
</body>
</html>

And we will see on the screen:

http://127.0.0.1:5000/

Hello DesarrolloLibre

You can customize the name by passing a parameter by get:

http://127.0.0.1:5000/?name=Andrew
Hello Andrew

In case you want to customize the name of the folder or location of the templates, you can define it when creating the main instance of the application:

app = Flask(__name__, template_folder="<ROUTETEMPLATES>")

We will see the different features that Jinja offers us, like the previous one, in detail in the next section.

First steps with Jinja

In this section we are going to learn about the main features of Jinja, which range from the use of control blocks to the use of filters and the template in general.

Control blocks

One of the crucial elements in template engines are control blocks; we can perform from conditionals to for loops that work in the same way as in Python; with this it is possible to create conditional logic to render HTML blocks if a condition is met, as well as iterate complete data collections, for example, a list of tasks in a table or the like.

Conditionals

We can make use of conditionals to evaluate true and false conditions:

<div>
    {% if True %}
        Is TRUE
    {% endif %}
</div>

Bucle for

Just like the for loop in Python, we can use it in Jinja:

<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

In a for loop block, you can access some special variables, the main ones being:

  • loop.index: Gets the current index of the iteration starting from one.
  • loop.index0: Gets the current index of the iteration starting from zero.
  • loop.first: True if this is the first iteration.
  • loop.last: True if it is the last iteration.
  • loop.length: Returns the length of the list.

For example, to use the variable last:

<ul>
    {% for e in [1,2,3,4,5,6,10] %}
    <li>{{ e }} {{ loop.last }} </li>
    {% endfor %}
</ul>

All variables must be used in the for loop.

Filters

Filters in Jinja are one of the most important and versatile features that exist in this template engine; allow you to manipulate the content displayed in a template. There are several predefined filters in Jinja although we can extend the existing ones with custom filters; the filters are applied to the variables that are used, for example, to count the length of a text string, join texts into one, separate by a separator, format dates, numbers and a long etc; in short, they allow for custom manipulations of the content.

To use a filter, use the pipe operator (|) after specifying the argument or arguments, and after the pipe operator, the filter you want to use:

<DATA> | <FILTER>

Let's look at some filters in Jinja.

Filter default

The default filter is used to replace the output if the variable has a null value (not defined):

{{ task | default('This is a default Task') }}

For example, if task is null, we will have an output like:

This is a default Task

If task were defined or we evaluated, for example, a number.

{{ 5 | default('This is a default Task') }}

We would see the number on the screen:

5

Filter escape

Replace the &, <, >, ', and " characters in the supplied string with safe characters to display text that contains the HTML characters:

{{ "<title>Todo Application</title>" | escape }}

We will have as output:

&lt;title1&gt;Todo Application&lt;/title1&gt;

Filter conversion

These filters include int and float filters used to convert from one data type to another:

{{ 3.142 | int }}

We will have as output:

3

Or for example:

{{ 31 | float }}

We will have as output:

31.0

Filter max

Returns the largest element in the list:

{{ [1, 2, 3, 4, 5]|max }}

And we will have:

5

Filter min

Returns the smallest element in the list:

{{ [1, 2, 3, 4, 5]|min }}

And we will have:

1

Blocks

Many of the functionalities that we can use in Jinja reside in blocks of code. These look like:

{% <BLOCKTYPE> %} 
<BODY>
{% <ENDBLOCKTYPE> %}

Code blocks allow both a better ordering for the code and to divide the block into sections using different types of blocks that allow a certain function to be performed.

Template inheritance

In this section, we will see how to use templates in Jinja; specifically how to use master templates to reuse a base skeleton in multiple views and how to include view fragments (other templates) in templates.

Template maestro

Many times it is necessary to have a master view where certain key content is updated; for example, if we have a management module, the common elements between the screen could be a header to define the links, as well as a logo, the footer and a container, the dynamic elements were presented in the middle of the screen.

In Jinja we can use master templates to implement this type of logic; in the end, a master view is nothing more than a template, where we have special blocks or sections (block) to indicate where the content that will change goes and this master template is included in the final templates and through the specified blocks in the master template, they are referenced in the final templates with the final content; this Jinja functionality is known as template inheritance.

Let's create a base or skeleton template that will be used to be inherited from other templates:

master.html

<!DOCTYPE html>
<html lang="es">
<head>
    {% block head %}
        <link rel="stylesheet" href="style.css" />
        <title>{% block title %}{% endblock %} - DesarrolloLibre</title>
    {% endblock %}
</head>
<body>
    <div id="content">{% block content %}{% endblock %}</div>
    <div id="footer">
        {% block footer %}
           DL by <a href="#">Contact</a>.
        {% endblock %}
    </div>
</body>
</html>

In the above code, 3 blocks are defined:

  1. One for the title in the header.
  2. One for the title in the content.
  3. Another for the content, which would be the place where we place the list, form among others.
Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.