Learning About Jinja / Introduction to Jinja

Reading some of the Jinja docs to learn something about it. I plan to use Jinja sometimes when using Flask in the backend for some API requests.

Jinja is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document.

References

Introduction

It includes:

Installation

$ pip install Jinja2

API

Basics

Jinja uses a central object called the template Environment. Instances of this class are used to store the configuration and global objects, and are used to load templates from the file system or other locations. Even if you are creating templates from strings by using the constructor of Template class, an environment is created automatically for you, albeit a shared one. Most applications will create one Environment object on application initialization and use that to load templates. In some cases, however, it's useful to have multiple environments side by side, if different configurations are in use.

from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
    loader=PackageLoader("yourapp"),
    autoescape=select_autoescape()
)

This will create a template environment with a loader that looks up templates in the templates folder inside the yourapp Python package (or next to the yourapp.py Python module). It also enables autoescaping for HTML files. This loader only requires that yourapp is importable, it figures out the absolute path to the folder for you.

To load a template from this environment, call the get_template() method, which returns the loaded Template.

template = env.get_template("mytemplate.html")

To render it with some variables, call the render() method.

print(template.render(the="variables", go="here"))

Template Designer Documentation

Synopsis

A Jinja template is simply a text file. Jinja can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). A Jinja template doesn't need to have a specific extension: .html, .xml, or any other extension is just fine. A template contains variables and/or expressions, which get replaced with values when a template is rendered, and tags, which control the logic of the template. The template syntax is heavily inspired by Django and Python. Below is a minimal template that illustrates a few basics using the default Jinja configuration:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>My Webpage</title>
</head>
<body>
    <ul id="navigation">
    {% for item in navigation %}
        <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
    {% endfor %}
    </ul>

    <h1>My Webpage</h1>
    {{ a_variable }}

    {# a comment #}
</body>
</html>

There are a few kinds of delimeters. The default Jinja delimiters are configured as follows:

You can add a .jinja extension to the filename of the template (like user.html.jinja) to make it easier for some IDEs or editor plugins, but it is not required. When accessing variables, if a variable or attribute does not exist, you will get back an undefined value.

Filters

Variables can be modified by filters. Filters are separated from the variable by a pipe symbol | and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is applied to the next. Examples:

Tests

Besides filters, there are also so-called "tests" available. Tests can be used to test a variable against a common expression. To test a variable or expression, you add is plus the name of the test after the variable. For example, to find out if a variable is defined, you can do name is defined, which will then return true or false depending on whether name is defined in the current context.

{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}

Escaping

Sometimes it is desireable to have Jinja ignore parts it would otherwise handle as variables or blocks. For example, if, with the default syntax, you want to use {{ as a raw string in a template and note start a variable, you have to use a tick. For bigger sections, it makes sense to mark a block raw:

{% raw %}
    <ul>
    {% for item in seq %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endraw %}

Template Inheritance

The most powerful part of Jinja is template inheritance. Template inheritance allows you to build a base "skeleton" template that contains all the common elements of your site and defines blocks that child templates can override.

Base Template

The base template below defines a simple HTML skeleton document that uou might use for a simple two-column page. It's the job of "child" templates to fill the empty blocks with content.

<!DOCTYPE html>
<html lang="en">
<head>
    {% block head %}
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}{% endblock %} - My Webpage</title>
    {% endblock %}
</head>
<body>
    <div id="content">{% block content %}{% endblock %}</div>
    <div id="footer">
        {% block footer %}
        &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
        {% endblock %}
    </div>
</body>
</html>

In this example, the {% block %} tags define four blocks that child templates can fill in. All the block tag does is tell the template engine that a child template may override those placeholders in the template.

Child Templates

A child template might look like this:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ super() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
      Welcome to my awesome homepage.
    </p>
{% endblock %}

The {% extends %} tag is the key here. It tells the template engine that this template "extends" another template. When the template system evaluates this template, it first locates the parent. The extends tag should be the first tag in the template. Everything before it is printed oyt normally and may cause confusion. The filename of the template depends on the template loader. You can access templates in subdirectories with a slash:

{% extends "layout/default.html" %}

You can't define multiple {% block %} tags with the same name in the same template. If you want to print a block multiple times, you can, however, use the special self variable and call the block with that name. Blocks can be marked as required. They must be overridden at some point, but not necessarily by the direct child template. Required blocks may only contain space and comments, and they cannot be rendered directly.

{% block body required %}{% endblock %}

HTML Escaping

Variables are automatically escaped by default in Jinja. Everything is escaped by default except for values explicitly marked as safe. Variables and expressions can be marked as safe either in:

  1. The content dictionary by the application of markupsafe.Markup
  2. The template, with the |safe filter.

If a value has been escaped but is not marked safe, auto-escaping will still take place and result in double-escaped characters.