Jinja

Личный сайт Go-разработчика из Казани

Getting Started with Jinja

Jinja is a fast, expressive, and extensible templating engine for Python applications.

Jinja includes a lot of functionalities, such as:

  • Template inheritance and inclusion;
  • Defining and importing macros within templates;
  • Security mechanisms to prevent XSS attacks;
  • A sandboxed environment that can safely render untrusted templates;
  • Extensible filters, tests, functions, and even syntax.

A Jinja template is simply a text file. Jinja doesn’t require a specific extension, but it’s common to use .j2 or .jinja to make it easier for some IDEs.

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

  • {% ... %} for Statements
  • {{ ... }} for Expressions to print to the template output
  • {# ... #} for Comments not included in the template output
1{# This is an example of a comment. #} 2 3{# 4 You can use this syntax 5 to write multiline comments 6 as well. 7#}

VARIABLES

1{# You have the option to access variables from the context passed to the template #} 2 3{{ foo }} 4 5{# 6 Additionally, you can use a dot (.) to access attributes of a variable or 7 use Python syntax, using [] 8#} 9 10{{ foo.bar }} 11{{ foo['bar'] }} 12 13{# Within the template, you can define variables as well #} 14 15{% set name = "Magdiel" %} 16{{ name }}

Loops

1<h1>Members</h1> 2<ul> 3{% for user in users %} 4 <li>{{ user.username }}</li> 5{% endfor %} 6</ul> 7 8 9<div> 10{% for key, value in my_dict.items() %} 11 <p>{{ key }}</p> - <p>{{ value }}</p> 12{% endfor %} 13</div> 14 15 16<div> 17{% for idx, url in enumerate(urls) %} 18 <a href="{{ url }}">Go to url {{ idx + 1 }}</a> 19{% endfor %} 20</div>

Conditionals

The if statement in Jinja is similar to the if statement in Python. It is commonly used to check if a variable is defined, not empty, and not false in its most basic form.

1{% if users %} 2<ul> 3{% for user in users %} 4 <li>{{ user.username }}</li> 5{% endfor %} 6</ul> 7{% endif %} 8 9 10{# For multiple branches, elif and else can be used like in Python. #} 11 12 13{% if message.status == "error" %} 14 <p class="text-red-400">{{ message.content }}</p> 15{% elif message.status == "success" %} 16 <p class="text-green-400">{{ message.content }}</p> 17{% else %} 18 <p class="text-blue-400">{{ message.content }}</p> 19{% endif %}

Template Inheritance

One of the most powerful features of Jinja is template inheritance. You can create a base layout with predefined blocks that you can extend in another file and override with your own content.

1{# file: base.html.j2 #} 2 3<!DOCTYPE html> 4<html lang="en"> 5<head> 6 {% block head %} 7 <meta charset="UTF-8"> 8 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 9 <title>{% block title %}{% endblock title %} - Learning Jinja</title> 10 {% endblock head %} 11</head> 12<body> 13 <main> 14 {% block content %}{% endblock %} 15 {# the endblock tag doesn't need the name of the block #} 16 </main> 17</body> 18</html> 19 20 21 22{# file: child.html.j2 #} 23 24{% extends "base.html.j2" %} 25 26{% block head %} 27 {{ super() }} 28 <script> 29 console.log("There's a console.log here") 30 </script> 31{% endblock %} 32 33{% block title %}Home{% endblock %} 34 35{% block content %} 36 <h1>Index</h1> 37 <p>Welcome to my home homepage.</p> 38{% endblock %} 39 40 41 42{# RESULT #} 43 44<!DOCTYPE html> 45<html lang="en"> 46<head> 47 <meta charset="UTF-8"> 48 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 49 <title>Home - Learning Jinja</title> 50 <script> 51 console.log("There's a console.log here") 52 </script> 53</head> 54<body> 55 <main> 56 <h1>Index</h1> 57 <p>Welcome to my home homepage.</p> 58 </main> 59</body> 60</html>

Including Content

You can include content from another template on your current template using the {% include "template/path" %} tag.

1{# file: footer.html.j2 #} 2 3<footer> 4 <p>&copy; 2024 - John Doe</p> 5</footer> 6 7 8 9{# file: index.html.j2 #} 10... 11<body> 12 <main> 13 <h1>Hi! I'm John Doe!</h1> 14 </main> 15 {% include "footer.html.j2" %} 16</body> 17... 18 19 20 21{# RESULT #} 22 23... 24<body> 25 <main> 26 <h1>Hi! I'm John Doe!</h1> 27 </main> 28 <footer> 29 <p>&copy; 2024 - John Doe</p> 30 </footer> 31</body> 32...

Variables passed to the main template can also be used in the include, as the included template has access to the context of the main template.

1{# file: greetings.html.j2 #} 2 3<p>I'm the {{ name }} and i like to {{ hobby }}.</p> 4 5 6 7{# file: index.html.j2 #} 8 9{% set name = "Captain Nemo" %} 10{% set hobby = "navigate through the depths of the ocean" %} 11 12<div> 13 {% include "greetings.html.j2" %} 14</div> 15 16 17 18{# RESULT #} 19 20<div> 21 <p>I'm the Captain Nemo and i like to navigate through the depths of the ocean.</p> 22</div>

Macros

Macros are basically like functions in another languages. You can define macros with or without arguments and reuse them in various parts of your template.

1{% macro input(value="", type="text", placeholder="") -%} 2 <input type="{{ type }}" value="{{ value }}" placeholder="{{ placeholder }}"> 3{%- endmacro %} 4 5<p>{{ input(placeholder="Your username") }}</p> 6<p>{{ input(type="password") }}</p>

Official Documentation

To learn more, access the official documentation.