Introduction

Jinja is a templating language for Python. It is used to generate dynamic content in web applications. It provides Python-like expressions inside HTML templates to generate content dynamically, rendered by the server. Official Documentation

Installation

Flask

Jinja is included in the Flask framework, so it is not necessary to install it separately.

pip install Flask

Delimiters

  • {% … %} for Statements
  • {{ … }} for Expressions
  • {# … #} for Comments

Template Inheritance

File structure
templates/
	base.html
	home.html
	

Simple Inheritance

base.html

Example of a base template for html pages

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
    {% block content %}
	<h1>
		Default Content
	</h1>
    {% endblock %} 
</body>  
</html>

home.html

Using the base template and overwriting the “content” block

{% extends "base.html" %}
 
{% block content %}
	<h1> This is my home page! </h1>
{% endblock %}

Abstract Base Template

base.html

base template for html pages, in which it must be overriden, but not necessairily by the direct child template, cannot be rendered directly

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
    {% block content required %}
    {% endblock %} 
</body>  
</html>

Template Inclusion

{% include 'header.html' %}
Body goes here.
{% include 'footer.html' %}

Conditional

If Statement

The if statement is used to check if a condition is true. It can be followed by an elif statement to check additional conditions, and an else statement to execute code when no conditions are met.

{% if variable == 42 %}
	<p> It is 42 </p>
{% elif variable %}
	<p> It is true </p>
{% else %}
	<p> It is false </p>
{% endif %}

Control Structures

For loop in list

The for loop is used to iterate over a list of items. It can be used to generate HTML elements dynamically.

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

For loop in dict

<dl>
{% for key, value in my_dict.items() %}
    <dt>{{ key }}</dt>
    <dd>{{ value }}</dd>
{% endfor %}
</dl>

Text Escaping

Adding |safe does automatic escaping of the content of the variable, useful for rendering HTML content from a variable when it is known to be safe and not untreated user-generated content.

{{variable|safe}}

Endpoint URL

Generate dynamic URLs for endpoints. It is useful to decouple the URL from the endpoint name, thus making it easier to change the URL in the future.

Usage
url_for('login')
app.py
from flask import Flask, render_template
 
app = Flask(__name__)
 
@app.route('/')
def home():
    return render_template('home.html')
 
@app.route('/auth/login')
def login():
    return render_template('login.html')
 
@app.route('/auth/register')
def register():
    return render_template('register.html')
...
template.html
<nav>  
    <ul>  
        <li><a href="/">
	        Home
        </a></li>  
        <li><a href="{{ url_for('login') }}">
	        Login
        </a></li>  
        <li><a href="{{ url_for('register') }}">
	        Register
        </a></li>  
    </ul>  
</nav>

It is generating the login and register URLs based on the function names in the app.py file.

Static files

The url_for function can be used to generate the URL for static files like CSS, JS, and images. To do this, the static folder must be created in the project root directory.

<link rel="stylesheet" 
	  href=" {{ url_for('static', filename='styles/shared/global.css') }}">

In this example, the global.css file is located in the styles/shared folder inside the static folder.

Macros

Macros are reusable code blocks that can be called multiple times with different parameters. They are useful for generating repetitive content in templates.

Declaration

macro.html
{% macro my_macro(parameter_1, parameter_2) %}
<div>
	This is my macro.
	{{parameter_1.name}} is awesome!
	<ul>
	{% for item in parameter_2 %}
		<li>
			{{item}}
		</li>
	{% endfor %}
	</ul>
</div>
{% endmacro %}

In this example, the macro my_macro takes two parameters: parameter_1 and parameter_2. It generates a div element with the content of the parameters. The parameter_1 is an object with a name attribute, and the parameter_2 is a list of items.

Usage

{% from 'macro.html' import my_macro %}
 
{{ my_macro({name: "cake"}, ["a", "b", "c"])}}

The from statement imports the macro from the macro.html file. The my_macro function is then called with the specified parameters.

Call With Children

When a macro is called with children, the content inside the call block is passed to the macro as the caller function.

{% macro render_dialog(title, class='dialog') -%}
    <div class="{{ class }}">
        <h2>{{ title }}</h2>
        <div class="contents">
            {{ caller() }}
        </div>
    </div>
{%- endmacro %}
 
{% call render_dialog('Hello World') %}
    <p>
        This is a simple dialog rendered by using a macro and
        a call block.
    </p>
{% endcall %}