Spec-Zone.ru › Jinja 3.1

Документация шаблонизатора

Этот документ описывает синтаксис и семантику движка шаблонов и будет полезен в первую очередь разработчикам, создающим шаблоны Jinja. Поскольку движок шаблонов очень гибкий, конфигурация из приложения может немного отличаться от показанного здесь кода в плане разделителей и поведения неопределённых значений.

Обзор

Шаблон Jinja — это просто текстовый файл. Jinja может генерировать любой текстовый формат (HTML, XML, CSV, LaTeX и т.д.). Шаблону Jinja не нужна конкретная расширение: .html, .xml, или любое другое расширение подойдёт.

Шаблон содержит переменные и/или выражения, которые заменяются значениями при рендеринге шаблона; и теги, которые управляют логикой шаблона. Синтаксис шаблона сильно вдохновлён Django и Python.

Ниже приведён минимальный шаблон, иллюстрирующий несколько основ с использованием стандартной конфигурации Jinja. Подробности будут рассмотрены позже в данном документе:

<!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>

Следующий пример демонстрирует стандартные настройки конфигурации. Разработчик приложения может изменить конфигурацию синтаксиса от {% foo %} до <% foo %>, или что-то подобное.

Существует несколько видов разделителей. Стандартные разделители Jinja настроены следующим образом:

  • {% ... %} для Операторов
  • {{ ... }} для Выражений для вывода в шаблон
  • {# ... #} для Комментарии, которые не включены в вывод шаблона

Операторы и комментарии на одной строке также возможны, хотя у них нет стандартных префиксов. Для их использования установите line_statement_prefix и line_comment_prefix при создании Environment.

Расширение файла шаблона

Как указано выше, любой файл может быть загружен как шаблон, независимо от расширения файла. Добавление расширения .jinja, например user.html.jinja, может упростить работу некоторых IDE или плагинов редакторов, но это необязательно. Автоэскейпинг, введённый позже, может применяться на основе расширения файла, поэтому в этом случае вам нужно учитывать дополнительный суффикс.

Ещё одним хорошим правилом для определения шаблонов является то, что они находятся в папке templates, независимо от расширения. Это распространённая структура для проектов.

Переменные

Переменные шаблона определяются в словаре контекста, переданном в шаблон.

Вы можете работать с переменными в шаблонах, если они переданы приложением. У переменных могут быть атрибуты или элементы, которые вы также можете получить. Какие атрибуты имеет переменная, в значительной степени зависит от приложения, предоставляющего эту переменную.

Вы можете использовать точку (.) для доступа к атрибутам переменной помимо стандартного синтаксиса Python __getitem__ «подстроки» ([]).

Следующие строки делают одно и то же:

{{ foo.bar }}
{{ foo['bar'] }}

Важно знать, что внешние двойные фигурные скобки — не часть переменной, а часть оператора вывода. Если вы обращаетесь к переменным внутри тегов, не ставьте фигурные скобки вокруг них.

Если переменная или атрибут не существуют, вы получите неопределённое значение. Что можно сделать с таким значением, зависит от конфигурации приложения: стандартное поведение — вывести пустую строку при выводе или итерации, и при других операциях — ошибка.

Реализация

Для удобства, foo.bar в Jinja выполняет следующие действия на уровне Python:

  • проверка наличия атрибута, названного bar на foo (getattr(foo, 'bar'))
  • если нет, проверка наличия элемента 'bar' в foo (foo.__getitem__('bar'))
  • если нет, возвращает неопределённый объект.

foo['bar'] работает почти так же, с небольшой разницей в последовательности:

  • проверка наличия элемента 'bar' в foo. (foo.__getitem__('bar'))
  • если нет, проверка наличия атрибута, названного bar на foo. (getattr(foo, 'bar'))
  • если нет, возвращает неопределённый объект.

Это важно, если у объекта есть элемент и атрибут с одинаковым именем. Кроме того, фильтр attr() ищет только атрибуты.

Фильтры

Переменные могут быть изменены с помощью фильтров. Фильтры отделяются от переменной символом «|» (|) и могут иметь необязательные аргументы в скобках. Можно использовать несколько фильтров. Результат одного фильтра применяется к следующему.

Например, {{ name|striptags|title }} удалит все HTML-теги из переменной name и приведёт результат к верхнему регистру (title(striptags(name))).

Фильтры, принимающие аргументы, имеют скобки вокруг аргументов, как вызов функции. Например: {{ listx|join(', ') }} соединит список запятыми (str.join(', ', listx)).

Список встроенных фильтров ниже описывает все встроенные фильтры.

Тесты

Помимо фильтров, также доступны так называемые «тесты». Тесты позволяют проверить переменную на соответствие определённому выражению. Чтобы проверить переменную или выражение, добавьте is и имя теста после переменной. Например, чтобы узнать, определена ли переменная, можно сделать name is defined, что вернёт true или false в зависимости от того, определена ли name в текущем контексте шаблона.

Тесты также могут принимать аргументы. Если тест принимает только один аргумент, вы можете опустить скобки. Например, следующие два выражения делают одно и то же:

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

Список встроенных тестов ниже описывает все встроенные тесты.

Комментарии

Для комментирования части строки в шаблоне используйте синтаксис комментария, который по умолчанию равен {# ... #}. Это полезно для комментирования частей шаблона для отладки или для добавления информации для других разработчиков шаблонов или для себя:

{# note: commented-out template because we no longer use this
    {% for user in users %}
        ...
    {% endfor %}
#}

Управление пробелами

В стандартной конфигурации:

  • единая конечная новая строка удаляется, если она есть
  • другие пробелы (пробелы, табуляции, новые строки и т.д.) возвращаются без изменений

Если приложение настраивает Jinja на trim_blocks, первая новая строка после тега шаблона удаляется автоматически (как в PHP). Опция lstrip_blocks также может быть настроена для удаления табуляций и пробелов с начала строки до начала блока. (Ничего не будет удалено, если перед началом блока есть другие символы.)

При включении как trim_blocks, так и lstrip_blocks, вы можете поместить теги блоков на отдельные строки, и вся строка блока будет удалена при рендеринге, сохраняя пробелы содержимого. Например, без опций trim_blocks и lstrip_blocks, этот шаблон:

<div>
    {% if True %}
        yay
    {% endif %}
</div>

рендерится с пустыми строками внутри div:

<div>

        yay

</div>

Но при включении как trim_blocks, так и lstrip_blocks, строки блоков шаблона удаляются, а другие пробелы сохраняются:

<div>
        yay
</div>

Вы можете вручную отключить поведение lstrip_blocks , поместив знак плюс (+) в начале блока:

<div>
        {%+ if something %}yay{% endif %}
</div>

Аналогично, вы можете вручную отключить поведение trim_blocks , поместив знак плюс (+) в конце блока:

<div>
    {% if something +%}
        yay
    {% endif %}
</div>

Вы также можете очистить пробелы в шаблонах вручную. Если вы добавите знак минус (-) в начало или конец блока (например, тега Цикл), комментария или выражения переменной, пробелы до или после этого блока будут удалены:

{% for item in seq -%}
    {{ item }}
{%- endfor %}

Это даст все элементы без пробелов между ними. Если seq был списком чисел от 1 до 9, вывод был бы 123456789.

Если операторы на одной строке включены, они автоматически удаляют начальные пробелы до начала строки.

По умолчанию Jinja также удаляет конечные новые строки. Чтобы сохранить отдельные конечные новые строки, настройте Jinja на keep_trailing_newline.

Примечание

Не добавляйте пробелы между тегом и знаком минус.

валидно:

{%- if foo -%}...{% endif %}

невалидно:

{% - if foo - %}...{% endif %}

Эскейпинг

Иногда желательно — даже необходимо — чтобы Jinja игнорировал части, которые в противном случае обрабатывались бы как переменные или блоки. Например, если с помощью стандартного синтаксиса вы хотите использовать {{ как строку в шаблоне, а не начинать переменную, вам придётся использовать трюк.

Самый простой способ вывести литеральный разделитель переменной ({{) — использовать выражение переменной:

{{ '{{' }}

Для больших разделов имеет смысл отметить блок raw. Например, чтобы включить пример синтаксиса Jinja в шаблон, можно использовать этот фрагмент:

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

Примечание

Знак минус в конце тега {% raw -%} очищает все пробелы и новые строки, предшествующие первому символу ваших необработанных данных.

Операторы на одной строке

Если операторы на одной строке включены приложением, можно пометить строку как оператор. Например, если префикс оператора на одной строке настроен на #, следующие два примера эквивалентны:

<ul>
# for item in seq
    <li>{{ item }}</li>
# endfor
</ul>

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

Префикс оператора на одной строке может быть где угодно в строке, пока текст перед ним отсутствует. Для лучшей читаемости операторы, начинающие блок (например, for, if, elif и т.д.) могут завершаться двоеточием:

# for item in seq:
    ...
# endfor

Примечание

Операторы на одной строке могут занимать несколько строк, если есть открывающие скобки, фигурные скобки или квадратные скобки:

<ul>
# for href, caption in [('index.html', 'Index'),
                        ('about.html', 'About')]:
    <li><a href="{{ href }}">{{ caption }}</a></li>
# endfor
</ul>

С Jinja 2.2 также доступны комментарии на основе строк. Например, если префикс комментария на одной строке настроен на ##, всё от ## до конца строки игнорируется (за исключением символа новой строки):

# for item in seq:
    <li>{{ item }}</li>     ## this comment is ignored
# endfor

Наследование шаблонов

Самой мощной частью Jinja является наследование шаблонов. Наследование шаблонов позволяет создать базовый «каркас» шаблона, содержащий все общие элементы вашего сайта и определять блоки, которые дочерние шаблоны могут переопределять.

Звучит сложно, но на самом деле очень просто. Проще всего понять это на примере.

Базовый шаблон

Этот шаблон, который мы назовем base.html, определяет простой HTML-каркас документа, который можно использовать для простой страницы с двумя колонками. «Дочерним» шаблонам необходимо заполнить пустые блоки содержимым:

<!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>

В этом примере теги {% block %} определяют четыре блока, которые могут быть заполнены дочерними шаблонами. Все, что делает тег block, — это сообщает движку шаблонов, что дочерний шаблон может переопределить эти заглушки в шаблоне.

Теги block могут быть внутри других блоков, таких как if, но они всегда будут выполняться независимо от того, будет ли блок if фактически отображаться.

Дочерний шаблон

Дочерний шаблон может выглядеть так:

{% 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 %}

Ключевой момент здесь — тег {% extends %}. Он сообщает движку шаблонов, что этот шаблон «расширяет» другой шаблон. Когда система шаблонов оценивает этот шаблон, она сначала находит родительский шаблон. Тег extends должен быть первым тегом в шаблоне. Все, что находится перед ним, печатается в обычном режиме и может привести к путанице. Подробности об этом поведении и о том, как им воспользоваться, см. в Null-Default Fallback. Также блок всегда будет заполнен, независимо от того, оценивается ли окружающее условие как истинное или ложное.

Имя файла шаблона зависит от загрузчика шаблонов. Например, FileSystemLoader позволяет получить доступ к другим шаблонам, указав имя файла. Вы можете получить доступ к шаблонам в подкаталогах с помощью косой черты:

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

Однако это поведение может зависеть от приложения, использующего Jinja. Обратите внимание, что поскольку дочерний шаблон не определяет блок footer, вместо этого используется значение из родительского шаблона.

Вы не можете определить несколько тегов {% block %} с одинаковым именем в одном и том же шаблоне. Это ограничение существует, потому что тег блока работает «в обоих» направлениях. То есть тег блока не только предоставляет заглушку для заполнения, но также определяет содержимое, которое заполняет заглушку в родительском шаблоне. Если в шаблоне были два тега с одинаковым именем {% block %}, родительский шаблон не знал бы, какое содержимое блока использовать.

Если вы хотите вывести блок несколько раз, вы можете использовать специальную переменную self и вызвать блок с этим именем:

<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}

Супер-блоки

Можно отобразить содержимое родительского блока, вызвав super(). Это возвращает результаты родительского блока:

{% block sidebar %}
    <h3>Table Of Contents</h3>
    ...
    {{ super() }}
{% endblock %}

Вложенные extends

В случае нескольких уровней {% extends %}, ссылки super могут быть объединены (как в super.super()) для пропуска уровней в дереве наследования.

Например:

# parent.tmpl
body: {% block body %}Hi from parent.{% endblock %}

# child.tmpl
{% extends "parent.tmpl" %}
{% block body %}Hi from child. {{ super() }}{% endblock %}

# grandchild1.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild1.{% endblock %}

# grandchild2.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}

Отображение child.tmpl даст body: Hi from child. Hi from parent.

Отображение grandchild1.tmpl даст body: Hi from grandchild1.

Отображение grandchild2.tmpl даст body: Hi from grandchild2. Hi from parent.

Именованные блоки и закрывающие теги

Jinja позволяет разместить имя блока после закрывающего тега для лучшей читаемости:

{% block sidebar %}
    {% block inner_sidebar %}
        ...
    {% endblock inner_sidebar %}
{% endblock sidebar %}

Однако имя после слова endblock должно совпадать с именем блока.

Вложенные блоки и область видимости

Блоки могут быть вложены для более сложных макетов. Однако по умолчанию блоки не могут получать доступ к переменным из внешних областей видимости:

{% for item in seq %}
    <li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}

Этот пример выведет пустые элементы <li>, потому что item недоступно внутри блока. Причина в том, что если блок заменяется дочерним шаблоном, появится переменная, которая не была определена в блоке или не была передана в контекст.

Начиная с Jinja 2.2, вы можете явно указать, что переменные доступны в блоке, установив блок как «скопированный», добавив модификатор scoped к объявлению блока:

{% for item in seq %}
    <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}

При переопределении блока модификатор scoped не должен предоставляться.

Обязательные блоки

Блоки могут быть помечены как required. Они должны быть переопределены в какой-то момент, но не обязательно непосредственным дочерним шаблоном. Обязательные блоки могут содержать только пробелы и комментарии, и они не могут быть отображены напрямую.

page.txt
{% block body required %}{% endblock %}
issue.txt
{% extends "page.txt" %}
bug_report.txt
{% extends "issue.txt" %}
{% block body %}Provide steps to demonstrate the bug.{% endblock %}

Отображение page.txt или issue.txt вызовет TemplateRuntimeError, потому что они не переопределяют блок body. Отображение bug_report.txt будет успешным, потому что оно переопределяет блок.

При объединении с scoped, модификатор required должен быть помещён после модификатора scoped. Вот несколько примеров:

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

Объекты шаблонов

extends, include, и import могут принимать объект шаблона вместо имени шаблона для загрузки. Это может быть полезно в некоторых сложных ситуациях, так как вы можете сначала загрузить шаблон с помощью кода Python и передать его в render.

if debug_mode:
    layout = env.get_template("debug_layout.html")
else:
    layout = env.get_template("layout.html")

user_detail = env.get_template("user/detail.html")
return user_detail.render(layout=layout)
{% extends layout %}

Обратите внимание, как extends получает переменную с объектом шаблона, переданным в render, а не строку.

Выполнение HTML-экранирования

При генерации HTML из шаблонов всегда существует риск, что переменная будет содержать символы, влияющие на получаемый HTML. Существует два подхода:

  1. ручное экранирование каждой переменной;
  2. автоматическое экранирование по умолчанию всего.

Jinja поддерживает оба подхода. Какой из них используется, зависит от конфигурации приложения. Конфигурация по умолчанию — без автоматического экранирования; по разным причинам:

  • Экранирование всего, кроме безопасных значений, также означает, что Jinja экранирует переменные, известные как не содержащие HTML (например, числа, булевы значения), что может привести к значительному снижению производительности.
  • Информация о безопасности переменной очень хрупка. Может случиться, что при принудительном преобразовании безопасных и небезопасных значений возвращаемое значение будет содержать двойное экранирование HTML.

Работа с ручным экранированием

Если ручное экранирование включено, вы несете ответственность за экранирование переменных при необходимости. Что экранировать? Если у вас есть переменная, которая может содержать любой из следующих символов (>, <, &, или "), вы ДОЛЖНЫ экранировать её, если переменная не содержит корректный и надёжный HTML. Экранирование выполняется путём прогонки переменной через фильтр |e.

{{ user.username|e }}

Работа с автоматическим экранированием

Когда автоматическое экранирование включено, всё экранируется по умолчанию, за исключением значений, явно помеченных как безопасные. Переменные и выражения можно пометить как безопасные либо в:

  1. словаре контекста приложением с markupsafe.Markup;
  2. шаблоне с помощью фильтра |safe.

Если строка, которую вы пометили как безопасную, передаётся через другой код Python, который не понимает эту метку, она может быть потеряна. Будьте внимательны к тому, когда ваши данные помечены как безопасные и как они обрабатываются перед поступлением в шаблон.

Если значение было экранировано, но не помечено как безопасное, автоматическое экранирование всё равно произойдёт и приведёт к двойному экранированию символов. Если вы знаете, что у вас есть данные, которые уже безопасны, но не помечены, убедитесь, что вы обернули их в Markup или используйте фильтр |safe.

Функции Jinja (макросы, super, self.BLOCKNAME) всегда возвращают данные шаблона, помеченные как безопасные.

Строковые литералы в шаблонах с автоматическим экранированием считаются небезопасными, потому что обычные строки Python не являются безопасными.

Список управляющих конструкций

Управляющая конструкция — это всё, что контролирует поток программы — условные операторы (например, if/elif/else), циклы for, а также такие вещи, как макросы и блоки. При использовании стандартного синтаксиса управляющие структуры находятся внутри блоков {% ... %}.

Цикл for

Итерирует по каждому элементу последовательности. Например, чтобы отобразить список пользователей, предоставленных в переменной users:

<h1>Members</h1>
<ul>
{% for user in users %}
  <li>{{ user.username|e }}</li>
{% endfor %}
</ul>

Так как переменные в шаблонах сохраняют свои свойства объекта, можно итерировать по контейнерам, таким как dict:

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

Порядок Python словарей может не совпадать с желаемым порядком отображения. Если порядок важен, используйте фильтр |dictsort.

<dl>
{% for key, value in my_dict | dictsort %}
    <dt>{{ key|e }}</dt>
    <dd>{{ value|e }}</dd>
{% endfor %}
</dl>

Внутри блока цикла for можно получить доступ к специальным переменным:

Переменная

Описание

loop.index

Текущая итерация цикла (индексируется с 1)

loop.index0

Текущая итерация цикла (индексируется с 0)

loop.revindex

Количество итераций с конца цикла (индексируется с 1)

loop.revindex0

Количество итераций с конца цикла (индексируется с 0)

loop.first

True, если первая итерация.

loop.last

True, если последняя итерация.

loop.length

Количество элементов в последовательности.

loop.cycle

Вспомогательная функция для циклического перебора списка последовательностей. См. объяснение ниже.

loop.depth

Указывает, на какой глубине в рекурсивном цикле в данный момент выполняется отображение. Начинается с уровня 1.

loop.depth0

Указывает, на какой глубине в рекурсивном цикле в данный момент выполняется отображение. Начинается с уровня 0.

loop.previtem

Элемент из предыдущей итерации цикла. Не определен во время первой итерации.

loop.nextitem

Элемент из следующей итерации цикла. Не определен во время последней итерации.

loop.changed(*val)

True, если ранее вызывалось с другим значением (или не вызывалось вообще).

Внутри цикла for можно циклически перебирать список строк/переменных на каждой итерации, используя специальную вспомогательную функцию loop.cycle:

{% for row in rows %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}

Начиная с Jinja 2.1, существует дополнительная вспомогательная функция cycle, которая позволяет осуществлять циклический перебор, не зависящий от цикла. Для получения дополнительной информации ознакомьтесь со списком глобальных функций Список глобальных функций.

В отличие от Python, невозможно break или continue в цикле. Однако вы можете фильтровать последовательность во время итерации, что позволяет пропускать элементы. Следующий пример пропускает всех скрытых пользователей:

{% for user in users if not user.hidden %}
    <li>{{ user.username|e }}</li>
{% endfor %}

Преимущества состоят в том, что специальная переменная loop будет подсчитывать правильно, не учитывая пользователей, не прошедших итерацию.

Если итерация не состоялась, потому что последовательность была пустой или фильтрация удалила все элементы из последовательности, вы можете отобразить блок по умолчанию, используя else:

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% else %}
    <li><em>no users found</em></li>
{% endfor %}
</ul>

Обратите внимание, что в Python блоки else выполняются всякий раз, когда соответствующий цикл не break. Поскольку циклы Jinja не могут break в любом случае, был выбран немного другой способ работы ключевого слова else.

Также можно использовать циклы рекурсивно. Это полезно, если вы работаете с рекурсивными данными, такими как карты сайта или RDFa. Чтобы использовать рекурсивные циклы, вам нужно добавить модификатор recursive к определению цикла и вызвать переменную loop с новой итерируемой последовательностью, где вы хотите сделать рекурсию.

Следующий пример реализует карту сайта с рекурсивными циклами:

<ul class="sitemap">
{%- for item in sitemap recursive %}
    <li><a href="{{ item.href|e }}">{{ item.title }}</a>
    {%- if item.children -%}
        <ul class="submenu">{{ loop(item.children) }}</ul>
    {%- endif %}</li>
{%- endfor %}
</ul>

Переменная loop всегда относится к ближайшему (вложенному) циклу. Если у нас есть более одного уровня циклов, мы можем переназначить переменную loop, написав {% set outer_loop = loop %} после цикла, который мы хотим использовать рекурсивно. Затем мы можем вызвать его с помощью {{ outer_loop(…) }}.

Обратите внимание, что присваивания в циклах будут очищены в конце итерации и не смогут существовать за пределами области цикла. В более старых версиях Jinja была ошибка, из-за которой в некоторых случаях казалось, что присваивания работают. Это не поддерживается. См. Присваивания для получения дополнительной информации о том, как справиться с этим.

Если всё, что вам нужно, это проверить, изменилось ли какое-либо значение с последней итерации или изменится на следующей, вы можете использовать previtem и nextitem:

{% for value in values %}
    {% if loop.previtem is defined and value > loop.previtem %}
        The value just increased!
    {% endif %}
    {{ value }}
    {% if loop.nextitem is defined and loop.nextitem > value %}
        The value will increase even more!
    {% endif %}
{% endfor %}

Если вас интересует только то, изменилось ли значение вообще, использование changed ещё проще:

{% for entry in entries %}
    {% if loop.changed(entry.category) %}
        <h2>{{ entry.category }}</h2>
    {% endif %}
    <p>{{ entry.message }}</p>
{% endfor %}

Условный оператор if

Оператор if в Jinja сравним с оператором if в Python. В простейшем виде можно использовать его для проверки, определена ли переменная, не пуста и не ложна:

{% if users %}
<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}

Для нескольких ветвей можно использовать elif и else, как и в Python. Там также можно использовать более сложные выражения:

{% if kenny.sick %}
    Kenny is sick.
{% elif kenny.dead %}
    You killed Kenny!  You bastard!!!
{% else %}
    Kenny looks okay --- so far
{% endif %}

Условный оператор if также может использоваться как встроенное выражение и для фильтрации циклов.

Макросы

Макросы аналогичны функциям в обычных языках программирования. Они полезны для размещения часто используемых выражений в повторно используемые функции, чтобы не повторяться («DRY»).

Вот небольшой пример макроса, который отрисовывает элемент формы:

{% macro input(name, value='', type='text', size=20) -%}
    <input type="{{ type }}" name="{{ name }}" value="{{
        value|e }}" size="{{ size }}">
{%- endmacro %}

Затем макрос можно вызывать, как функцию в пространстве имён:

<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>

Если макрос был определён в другом шаблоне, его нужно сначала импортировать.

Внутри макросов есть доступ к трём специальным переменным:

varargs

Если в макрос передано больше позиционных аргументов, чем он принимает, они попадают в специальную переменную varargs в виде списка значений.

kwargs

Аналогично varargs, но для именованных аргументов. Все неиспользованные именованные аргументы хранятся в этой специальной переменной.

caller

Если макрос был вызван из тега вызова, вызывающий элемент хранится в этой переменной в виде вызываемого макроса.

Макросы также предоставляют некоторые из своих внутренних деталей. На объекте макроса доступны следующие атрибуты:

name

Имя макроса. {{ input.name }} выведет input.

arguments

Кортеж имён аргументов, которые принимает макрос.

catch_kwargs

Это true, если макрос принимает дополнительные именованные аргументы (т. е. обращается к специальной переменной kwargs).

catch_varargs

Это true, если макрос принимает дополнительные позиционные аргументы (т. е. обращается к специальной переменной varargs).

caller

Это true, если макрос обращается к специальной переменной caller и может вызываться из тега вызова.

Если имя макроса начинается с нижнего подчёркивания, оно не экспортируется и не может быть импортировано.

Из-за того, как работают области видимости в Jinja, макрос в дочернем шаблоне не переопределяет макрос в родительском шаблоне. Следующее выведет «LAYOUT», а не «CHILD».

layout.txt
{% macro foo() %}LAYOUT{% endmacro %}
{% block body %}{% endblock %}
child.txt
{% extends 'layout.txt' %}
{% macro foo() %}CHILD{% endmacro %}
{% block body %}{{ foo() }}{% endblock %}

Вызов

В некоторых случаях может быть полезно передать макрос в другой макрос. Для этого можно использовать специальный блок call. Следующий пример показывает макрос, который использует функциональность вызова, и как его использовать:

{% macro render_dialog(title, class='dialog') -%}
    <div class="{{ class }}">
        <h2>{{ title }}</h2>
        <div class="contents">
            {{ caller() }}
        </div>
    </div>
{%- endmacro %}

{% call render_dialog('Hello World') %}
    This is a simple dialog rendered by using a macro and
    a call block.
{% endcall %}

Также возможно передавать аргументы обратно в блок вызова. Это делает его полезным как замену циклов. В общем случае, блок вызова работает точно так же, как и макрос без имени.

Вот пример использования блока вызова с аргументами:

{% macro dump_users(users) -%}
    <ul>
    {%- for user in users %}
        <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
    {%- endfor %}
    </ul>
{%- endmacro %}

{% call(user) dump_users(list_of_user) %}
    <dl>
        <dt>Realname</dt>
        <dd>{{ user.realname|e }}</dd>
        <dt>Description</dt>
        <dd>{{ user.description }}</dd>
    </dl>
{% endcall %}

Фильтры

Разделы фильтров позволяют применять стандартные фильтры Jinja к блоку данных шаблона. Просто оберните код в специальный раздел filter:

{% filter upper %}
    This text becomes uppercase
{% endfilter %}

Фильтры, принимающие аргументы, можно вызывать следующим образом:

{% filter center(100) %}Center this{% endfilter %}

Присваивания

Внутри блоков кода также можно присваивать значения переменным. Присваивания на верхнем уровне (вне блоков, макросов или циклов) экспортируются из шаблона как макросы верхнего уровня и могут быть импортированы другими шаблонами.

Присваивания используют тег set и могут иметь несколько целей:

{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}

Поведение области видимости

Пожалуйста, имейте в виду, что присваивание переменных внутри блока не приводит к их появлению вне этого блока. Это также относится к циклам. Исключение составляют условные операторы if, которые не вводят область видимости. В результате следующий шаблон не будет работать так, как вы ожидаете:

{% set iterated = false %}
{% for item in seq %}
    {{ item }}
    {% set iterated = true %}
{% endfor %}
{% if not iterated %} did not iterate {% endif %}

Это невозможно сделать с помощью синтаксиса Jinja. Вместо этого используйте альтернативные конструкции, такие как блок else в цикле или специальную переменную loop:

{% for item in seq %}
    {{ item }}
{% else %}
    did not iterate
{% endfor %}

Начиная с версии 2.10, более сложные случаи могут быть обработаны с использованием объектов пространства имён, которые позволяют распространять изменения через области видимости:

{% set ns = namespace(found=false) %}
{% for item in items %}
    {% if item.check_something() %}
        {% set ns.found = true %}
    {% endif %}
    * {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}

Обратите внимание, что обозначение obj.attr в теге set разрешено только для объектов пространства имён; попытка присвоить атрибут любому другому объекту вызовет исключение.

Журнал изменений

В версии 2.10: Добавлена поддержка объектов пространства имён

Блочные присваивания

Журнал изменений

Новое в версии 2.8.

Начиная с Jinja 2.8, можно также использовать блочные присваивания для захвата содержимого блока в имя переменной. Это может быть полезно в некоторых ситуациях как альтернатива макросам. В этом случае вместо использования знака равенства и значения, вы просто записываете имя переменной, а затем всё до {% endset %}. будет захвачено.

Пример:

{% set navigation %}
    <li><a href="/">Index</a>
    <li><a href="/downloads">Downloads</a>
{% endset %}

Переменная navigation затем содержит исходный HTML-код навигации.

Журнал изменений

Изменено в версии 2.10.

Начиная с Jinja 2.10, блочное присваивание поддерживает фильтры.

Пример:

{% set reply | wordwrap %}
    You wrote:
    {{ message }}
{% endset %}

Расширения

Тег extends может использоваться для расширения одной темы от другой. Вы можете иметь несколько тегов extends в файле, но только один из них может быть выполнен в одно время.

См. раздел о Наследование шаблонов выше.

Блоки

Блоки используются для наследования и действуют как заглушки и замены одновременно. Они подробно описаны в разделе Наследование шаблонов.

Включение

Тег include рендерит другой шаблон и выводит результат в текущий шаблон.

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

Включённый шаблон по умолчанию имеет доступ к контексту текущего шаблона. Используйте without context для использования отдельного контекста вместо этого. with context также допустимо, но является стандартным поведением. См. Поведение контекста импорта.

Включённый шаблон может extend другой шаблон и переопределять блоки в этом шаблоне. Однако текущий шаблон не может переопределять какие-либо блоки, которые выводит включённый шаблон.

Используйте ignore missing для игнорирования оператора, если шаблон не существует. Он должен быть помещён перед оператором видимости контекста.

{% include "sidebar.html" without context %}
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}

Если задан список шаблонов, каждый будет проверен в порядке следования, пока не будет найден тот, который отсутствует. Это можно использовать с ignore missing для игнорирования, если ни один из шаблонов не существует.

{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}

Переменная с именем шаблона или объектом шаблона также может быть передана в оператор.

Импорт

Jinja поддерживает размещение часто используемого кода в макросах. Эти макросы могут быть помещены в разные шаблоны и импортированы оттуда. Это работает аналогично операторам импорта в Python. Важно знать, что импорты кэшируются, а импортированные шаблоны не имеют доступа к переменным текущего шаблона, только к глобальным по умолчанию. Более подробную информацию о поведении контекста импорта и включения см. в разделе Поведение контекста импорта.

Есть два способа импортировать шаблоны. Можно импортировать весь шаблон в переменную или запросить определённые макросы/экспортированные переменные из него.

Представьте, что у нас есть модуль помощник, который рендерит формы (называемый forms.html):

{% macro input(name, value='', type='text') -%}
    <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}

{%- macro textarea(name, value='', rows=10, cols=40) -%}
    <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
        }}">{{ value|e }}</textarea>
{%- endmacro %}

Самый простой и гибкий способ доступа к переменным и макросам шаблона — импортировать весь модуль шаблона в переменную. Таким образом, вы можете получить доступ к атрибутам:

{% import 'forms.html' as forms %}
<dl>
    <dt>Username</dt>
    <dd>{{ forms.input('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>

В качестве альтернативы вы можете импортировать определённые имена из шаблона в текущее пространство имён:

{% from 'forms.html' import input as input_field, textarea %}
<dl>
    <dt>Username</dt>
    <dd>{{ input_field('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>

Макросы и переменные, начинающиеся с одной или нескольких нижних подчеркиваний, являются приватными и не могут быть импортированы.

Журнал изменений

Изменено в версии 2.4: Если объекту шаблона был передан объект шаблона в контекст шаблона, вы можете импортировать из этого объекта.

Поведение контекста импорта

По умолчанию включённые шаблоны получают текущий контекст, а импортированные — нет. Причина в том, что импорты, в отличие от включений, кешируются; импорты часто используются как модуль, содержащий макросы.

Это поведение можно явно изменить: добавив with context или without context к директиве import/include, текущий контекст может быть передан шаблону, а кэширование автоматически отключено.

Вот два примера:

{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}

Примечание

В Jinja 2.0 контекст, который передавался включённому шаблону, не включал переменные, определённые в шаблоне. Фактически, это не работало:

{% for box in boxes %}
    {% include "render_box.html" %}
{% endfor %}

Включённый шаблон render_box.html не может получить доступ к box в Jinja 2.0. Начиная с Jinja 2.1, render_box.html может это сделать.

END_OF_DOCUMENT_MARKER

Выражения

Jinja позволяет использовать базовые выражения везде. Они работают очень похоже на обычный Python; даже если вы не работаете с Python, вы должны чувствовать себя комфортно.

Литералы

Простейшей формой выражений являются литералы. Литералы представляют собой представления объектов Python, таких как строки и числа. Существуют следующие литералы:

"Hello World"

Всё, что находится между двумя двойными или одинарными кавычками, — это строка. Они полезны всякий раз, когда вам нужна строка в шаблоне (например, в качестве аргументов вызовов функций и фильтров или просто для расширения или включения шаблона).

42 / 123_456

Целые числа — это целые числа без дробной части. Символ «_» может быть использован для разделения групп для повышения читабельности.

42.23 / 42.1e2 / 123_456.789

Вещественные числа могут быть записаны с использованием «.» в качестве десятичной точки. Их также можно записать в экспоненциальной форме с использованием «e» или «E» для обозначения порядка. Символ «_» может быть использован для разделения групп для повышения читабельности, но не может быть использован в экспоненциальной части.

['list', 'of', 'objects']

Всё, что находится между двумя скобками, — это список. Спискки полезны для хранения последовательных данных, которые нужно итерировать. Например, вы можете легко создать список ссылок, используя списки и кортежи для цикла for:

<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
                         ('downloads.html', 'Downloads')] %}
    <li><a href="{{ href }}">{{ caption }}</a></li>
{% endfor %}
</ul>
('tuple', 'of', 'values')

Кортежи похожи на списки, но их нельзя изменить («неизменяемые»). Если кортеж содержит только один элемент, после него должен стоять запятая (('1-tuple',)). Кортежи обычно используются для представления элементов из двух или более элементов. Более подробную информацию см. в примере списка выше.

{'dict': 'of', 'key': 'and', 'value': 'pairs'}

Словарь в Python — это структура, которая объединяет ключи и значения. Ключи должны быть уникальными и всегда иметь ровно одно значение. Словари редко используются в шаблонах; они полезны в некоторых редких случаях, например, в фильтре xmlattr().

true / false

true всегда истинно, а false всегда ложно.

Примечание

Специальные константы true, false, и none действительно пишутся с маленькой буквы. Поскольку это вызвало путаницу в прошлом (True раньше расширялся до неопределённой переменной, которая считалась ложной), все три теперь также могут быть написаны с заглавной буквы (True, False, и None). Однако для единообразия (все идентификаторы Jinja являются строчными) следует использовать версии с маленькой буквы.

Математика

Jinja позволяет выполнять вычисления со значениями. Это редко бывает полезно в шаблонах, но существует для полноты. Поддерживаются следующие операторы:

+

Складывает два объекта вместе. Обычно объекты — это числа, но если оба являются строками или списками, вы можете конкатенировать их таким образом. Однако это не предпочтительный способ конкатенации строк! Для конкатенации строк обратите внимание на оператор ~. {{ 1 + 1 }} это 2.

-

Вычитает второе число из первого. {{ 3 - 2 }} это 1.

/

Делит два числа. Возвращаемое значение будет вещественным числом. {{ 1 / 2 }} это {{ 0.5 }}.

//

Делит два числа и возвращает усечённое целое значение. {{ 20 // 7 }} это 2.

%

Вычисляет остаток от целочисленного деления. {{ 11 % 7 }} это 4.

*

Умножает левый операнд на правый. {{ 2 * 2 }} вернёт 4. Это также можно использовать для многократного повторения строки. {{ '=' * 80 }} отобразит полосу из 80 одинаковых знаков.

**

Возводит левый операнд в степень правого. {{ 2**3 }} вернёт 8.

В отличие от Python, цепочки pow вычисляются слева направо. {{ 3**3**3 }} вычисляется как (3**3)**3 в Jinja, но вычислялось бы как 3**(3**3) в Python. Используйте скобки в Jinja, чтобы явно указать желаемый порядок. Обычно лучше выполнять расширенные математические вычисления в Python и передавать результаты в render вместо этого.

Это поведение может быть изменено в будущем, чтобы соответствовать Python, если это возможно.

Сравнения

==

Сравнивает два объекта на равенство.

!=

Сравнивает два объекта на неравенство.

>

true если левая часть больше правой.

>=

true если левая часть больше или равна правой.

<

true если левая часть меньше правой.

<=

true если левая часть меньше или равна правой.

Логика

Для операторов if, for фильтрации и if выражений может быть полезно объединение нескольких выражений:

and

Возвращает истинное значение, если левый и правый операнды истинны.

or

Возвращает истинное значение, если левый или правый операнды истинны.

not

Отрицает утверждение (см. ниже).

(expr)

Скобки группируют выражение.

Примечание

Операторы is и in также поддерживают отрицание с использованием инфиксной нотации: foo is not bar и foo not in bar вместо not foo is bar и not foo in bar. Все остальные выражения требуют префиксной нотации: not (foo and bar).

Другие операторы

Следующие операторы очень полезны, но не подходят ни к одной из других двух категорий:

in

Выполняет проверку на принадлежность последовательности/отображения. Возвращает true, если левый операнд содержится в правом. {{ 1 in [1, 2, 3] }} вернет, например, true.

is

Выполняет тест.

| (pipe, vertical bar)

Применяет фильтр.

~ (tilde)

Преобразует все операнды в строки и конкатенирует их.

{{ "Hello " ~ name ~ "!" }} вернёт (если name установлено в 'John') Hello John!.

()

Вызов вызываемого объекта: {{ post.render() }}. В скобках можно использовать позиционные и именованные аргументы, как в Python:

{{ post.render(user, full=true) }}.

. / []

Получить атрибут объекта. (См. Переменные)

Выражение if

Также можно использовать встроенные выражения if. Они полезны в некоторых ситуациях. Например, вы можете использовать это для расширения из одного шаблона, если переменная определена, в противном случае из шаблона по умолчанию:

{% extends layout_template if layout_template is defined else 'default.html' %}

Общая синтаксис <do something> if <something is true> else <do something else>.

Часть else необязательна. Если она не указана, блок else неявно вычисляется в объект Undefined (независимо от того, что undefined установлено в среде):

{{ "[{}]".format(page.title) if page.title }}

Методы Python

Вы также можете использовать любые методы, определённые для типа переменной. Возвращаемое значение вызова метода используется в качестве значения выражения. Вот пример использования методов, определённых для строк (где page.title является строкой):

{{ page.title.capitalize() }}

Это работает для методов пользовательских типов. Например, если переменная f типа Foo имеет определённый метод bar, вы можете сделать следующее:

{{ f.bar(value) }}

Операторные методы также работают как ожидается. Например, % реализует форматирование строк в стиле printf:

{{ "Hello, %s!" % name }}

Хотя для этого случая предпочтительнее метод .format (который немного придуман в контексте рендеринга шаблона):

{{ "Hello, {}!".format(name) }}

Список встроенных фильтров

abs()

forceescape()

map()

select()

unique()

attr()

format()

max()

selectattr()

upper()

batch()

groupby()

min()

slice()

urlencode()

capitalize()

indent()

pprint()

sort()

urlize()

center()

int()

random()

string()

wordcount()

default()

items()

reject()

striptags()

wordwrap()

dictsort()

join()

rejectattr()

sum()

xmlattr()

escape()

last()

replace()

title()

filesizeformat()

length()

reverse()

tojson()

first()

list()

round()

trim()

float()

lower()

safe()

truncate()

jinja-filters.abs(x, /)

Возвращает абсолютное значение аргумента.

jinja-filters.attr(obj: Any, name: str) → jinja2.runtime.Undefined | Any

Получение атрибута объекта. foo|attr("bar") работает как foo.bar, только всегда возвращает атрибут, а не ищет элементы.

См. Примечания по подпискам для получения дополнительных сведений.

jinja-filters.batch(value: 't.Iterable[V]', linecount: int, fill_with: 't.Optional[V]' = None) → 't.Iterator[t.List[V]]'

Фильтр, который группирует элементы. Он работает примерно так же, как slice, только в обратном порядке. Он возвращает список списков с заданным количеством элементов. Если вы предоставите второй параметр, он используется для заполнения недостающих элементов. Посмотрите этот пример:

<table>
{%- for row in items|batch(3, '&nbsp;') %}
  <tr>
  {%- for column in row %}
    <td>{{ column }}</td>
  {%- endfor %}
  </tr>
{%- endfor %}
</table>
jinja-filters.capitalize(s: str) → str

Преобразовать значение в верхний регистр. Первый символ будет заглавным, все остальные – строчными.

jinja-filters.center(value: str, width: int = 80) → str

Выравнивание значения по центру в поле заданной ширины.

jinja-filters.default(value: V, default_value: V = '', boolean: bool = False) → V

Если значение не определено, возвращает переданное значение по умолчанию, в противном случае – значение переменной:

{{ my_variable|default('my_variable is not defined') }}

Это выведет значение my_variable, если переменная была определена, в противном случае – 'my_variable is not defined'. Если вы хотите использовать значение по умолчанию с переменными, оцениваемыми как ложные, вы должны установить второй параметр в true:

{{ ''|default('the string was empty', true) }}
Журнал изменений

Изменено в версии 2.11: Теперь можно настроить Environment с помощью ChainableUndefined, чтобы фильтр default работал с вложенными элементами и атрибутами, которые могут содержать неопределенные значения в цепочке, не получая UndefinedError.

Псевдонимы:

d

jinja-filters.dictsort(value: Mapping[K, V], case_sensitive: bool = False, by: 'te.Literal["key", "value"]' = 'key', reverse: bool = False) → List[Tuple[K, V]]

Сортирует словарь и возвращает пары (ключ, значение). Словари Python могут не быть отсортированы в желаемом порядке, поэтому их нужно отсортировать.

{% for key, value in mydict|dictsort %}
    sort the dict by key, case insensitive

{% for key, value in mydict|dictsort(reverse=true) %}
    sort the dict by key, case insensitive, reverse order

{% for key, value in mydict|dictsort(true) %}
    sort the dict by key, case sensitive

{% for key, value in mydict|dictsort(false, 'value') %}
    sort the dict by value, case insensitive
jinja-filters.escape(value)

Заменяет символы &, <, >, ', и " в строке на безопасные для HTML последовательности. Используйте это, если вам нужно отобразить текст, который может содержать такие символы в HTML.

Если у объекта есть метод __html__, он вызывается, и возвращаемое значение предполагается безопасным для HTML.

Параметры:

s – Объект, который нужно преобразовать в строку и экранировать.

Возвращаемое значение:

Строка Markup с экранированным текстом.

Псевдонимы:

e

jinja-filters.filesizeformat(value: str | float | int, binary: bool = False) → str

Форматирует значение как «человекочитаемый» размер файла (например, 13 КБ, 4,1 МБ, 102 байта и т. д.). По умолчанию используются десятичные префиксы (Мега, Гига и т. д.), если второй параметр установлен в True, используются двоичные префиксы (Меби, Гиби).

jinja-filters.first(seq: 't.Iterable[V]') → 't.Union[V, Undefined]'

Возвращает первый элемент последовательности.

jinja-filters.float(value: Any, default: float = 0.0) → float

Преобразует значение в число с плавающей точкой. Если преобразование не удается, возвращает 0.0. Вы можете переопределить это значение по умолчанию, используя первый параметр.

END_OF_DOCUMENT_MARKER
jinja-filters.forceescape(value: 't.Union[str, HasHTML]') → markupsafe.Markup

Принудительное экранирование HTML. Вероятно, произойдёт двойное экранирование переменных.

jinja-filters.format(value: str, *args: Any, **kwargs: Any) → str

Применение заданных значений к строке форматирования в стиле printf, как string % values.

{{ "%s, %s!"|format(greeting, name) }}
Hello, World!

В большинстве случаев будет удобнее и эффективнее использовать оператор % или str.format().

{{ "%s, %s!" % (greeting, name) }}
{{ "{}, {}!".format(greeting, name) }}
jinja-filters.groupby(value: 't.Iterable[V]', attribute: str | int, default: Any | None = None, case_sensitive: bool = False) → 't.List[_GroupTuple]'

Группировка последовательности объектов по атрибуту с использованием Python’s itertools.groupby(). Атрибут может использовать нотацию точки для вложенного доступа, как "address.city". В отличие от Python’s groupby, значения сначала сортируются, поэтому для каждого уникального значения возвращается только одна группа.

Например, список объектов User с атрибутом city может быть отображён группами. В данном примере grouper ссылается на значение city группы.

<ul>{% for city, items in users|groupby("city") %}
  <li>{{ city }}
    <ul>{% for user in items %}
      <li>{{ user.name }}
    {% endfor %}</ul>
  </li>
{% endfor %}</ul>

groupby возвращает именованные кортежи (grouper, list), которые могут быть использованы вместо распаковки кортежа выше. list — это значение атрибута, а list — это элементы с этим значением.

<ul>{% for group in users|groupby("city") %}
  <li>{{ group.grouper }}: {{ group.list|join(", ") }}
{% endfor %}</ul>

Можно указать значение default, которое будет использоваться, если у объекта в списке нет заданного атрибута.

<ul>{% for city, items in users|groupby("city", default="NY") %}
  <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li>
{% endfor %}</ul>

Как и фильтр sort(), сортировка и группировка по умолчанию регистронезависимы. Значение key для каждой группы будет иметь регистр первого элемента в этой группе значений. Например, если список пользователей имеет города ["CA", "NY", "ca"], группа «CA» будет иметь два значения. Это можно отключить, передав case_sensitive=True.

Изменено в версии 3.1: Добавлен параметр case_sensitive. Сортировка и группировка по умолчанию регистронезависимы, соответствуя другим фильтрам, выполняющим сравнения.

Журнал изменений

Изменено в версии 3.0: Добавлен параметр default.

Изменено в версии 2.6: Атрибут поддерживает нотацию точки для вложенного доступа.

jinja-filters.indent(s: str, width: int | str = 4, first: bool = False, blank: bool = False) → str

Возвращает копию строки с каждой строкой, отступающей на 4 пробела. Первая строка и пустые строки по умолчанию не отступаются.

Параметры:
  • width – Количество пробелов или строка для отступа.
  • first – Не пропускать отступ первой строки.
  • blank – Не пропускать отступ пустых строк.
Журнал изменений

Изменено в версии 3.0: width может быть строкой.

Изменено в версии 2.10: Пустые строки по умолчанию не отступаются.

Переименовано аргумент indentfirst в first.

jinja-filters.int(value: Any, default: int = 0, base: int = 10) → int

Преобразование значения в целое число. Если преобразование не выполнено, возвращается 0. Можно переопределить это значение по умолчанию, используя первый параметр. Также можно переопределить значение базы по умолчанию (10) во втором параметре, который обрабатывает входные данные с префиксами, такими как 0b, 0o и 0x для баз 2, 8 и 16 соответственно. База игнорируется для десятичных чисел и значений, отличных от строк.

jinja-filters.items(value: Mapping[K, V] | jinja2.runtime.Undefined) → Iterator[Tuple[K, V]]

Возвращает итератор по (key, value) элементам отображения.

x|items эквивалентно x.items(), за исключением случаев, когда x не определено, возвращается пустой итератор.

Этот фильтр полезен, если вы ожидаете, что шаблон будет отображаться с реализацией Jinja на другом языке программирования, у которого нет метода .items() для типа отображения.

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

Введено в версии 3.1.

jinja-filters.join(value: Iterable, d: str = '', attribute: str | int | NoneType = None) → str

Возвращает строку, являющуюся конкатенацией строк в последовательности. Разделитель между элементами по умолчанию — пустая строка, можно определить его с помощью необязательного параметра:

{{ [1, 2, 3]|join('|') }}
    -> 1|2|3

{{ [1, 2, 3]|join }}
    -> 123

Также можно объединить определённые атрибуты объекта:

{{ users|join(', ', attribute='username') }}
Журнал изменений

Введено в версии 2.6: Добавлен параметр attribute.

jinja-filters.last(seq: 't.Reversible[V]') → 't.Union[V, Undefined]'

Возвращает последний элемент последовательности.

Примечание: Не работает с генераторами. Вы можете явно преобразовать его в список:

{{ data | selectattr('name', '==', 'Jinja') | list | last }}
jinja-filters.length(obj, /)

Возвращает количество элементов в контейнере.

Псевдонимы:

count

jinja-filters.list(value: 't.Iterable[V]') → 't.List[V]'

Преобразование значения в список. Если это была строка, возвращаемый список будет списком символов.

jinja-filters.lower(s: str) → str

Преобразование значения в нижний регистр.

jinja-filters.map(value: Iterable, *args: Any, **kwargs: Any) → Iterable

Применяет фильтр к последовательности объектов или ищет атрибут. Это полезно при работе со списками объектов, но вас интересует только определённое значение.

Основное использование — отображение по атрибуту. Представьте, у вас есть список пользователей, но вас интересует только список имён пользователей:

Users on this page: {{ users|map(attribute='username')|join(', ') }}

Можно указать значение default, которое будет использоваться, если у объекта в списке нет заданного атрибута.

{{ users|map(attribute="username", default="Anonymous")|join(", ") }}

В качестве альтернативы можно вызвать фильтр, передав имя фильтра и последующие аргументы. Хорошим примером является применение фильтра преобразования текста к последовательности:

Users on this page: {{ titles|map('lower')|join(', ') }}

Аналогично генераторному выражению:

(u.username for u in users)
(getattr(u, "username", "Anonymous") for u in users)
(do_lower(x) for x in titles)
Журнал изменений

Изменено в версии 2.11.0: Добавлен параметр default.

Введено в версии 2.7.

jinja-filters.max(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: str | int | NoneType = None) → 't.Union[V, Undefined]'

Возвращает наибольший элемент из последовательности.

{{ [1, 2, 3]|max }}
    -> 3
Параметры:
  • case_sensitive – Рассматривать строчные и прописные буквы как разные.
  • attribute – Получить объект с максимальным значением этого атрибута.
jinja-filters.min(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: str | int | NoneType = None) → 't.Union[V, Undefined]'

Возвращает наименьший элемент из последовательности.

{{ [1, 2, 3]|min }}
    -> 1
Параметры:
  • case_sensitive – Рассматривать строчные и прописные буквы как разные.
  • attribute – Получить объект с минимальным значением этого атрибута.
jinja-filters.pprint(value: Any) → str

Красивая печать переменной. Полезно для отладки.

jinja-filters.random(seq: 't.Sequence[V]') → 't.Union[V, Undefined]'

Возвращает случайный элемент из последовательности.

jinja-filters.reject(value: 't.Iterable[V]', *args: Any, **kwargs: Any) → 't.Iterator[V]'

Фильтрует последовательность объектов, применяя тест к каждому объекту и отбрасывая объекты, для которых тест успешен.

Если тест не указан, каждый объект оценивается как булево значение.

Пример использования:

{{ numbers|reject("odd") }}

Аналогично генераторному выражению:

(n for n in numbers if not test_odd(n))
Журнал изменений

Введено в версии 2.7.

jinja-filters.rejectattr(value: 't.Iterable[V]', *args: Any, **kwargs: Any) → 't.Iterator[V]'

Фильтрует последовательность объектов, применяя тест к указанному атрибуту каждого объекта и отбрасывая объекты, для которых тест успешен.

Если тест не указан, значение атрибута оценивается как булево значение.

{{ users|rejectattr("is_active") }}
{{ users|rejectattr("email", "none") }}

Аналогично генераторному выражению:

(u for user in users if not user.is_active)
(u for user in users if not test_none(user.email))
Журнал изменений

Введено в версии 2.7.

jinja-filters.replace(s: str, old: str, new: str, count: int | None = None) → str

Возвращает копию значения со всеми вхождениями подстроки, заменёнными новой. Первый аргумент — подстрока, которая должна быть заменена, второй — строка замены. Если необязательный третий аргумент count задан, заменяются только первые count вхождений:

{{ "Hello World"|replace("Hello", "Goodbye") }}
    -> Goodbye World

{{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
    -> d'oh, d'oh, aaargh
jinja-filters.reverse(value: str | Iterable[V]) → str | Iterable[V]

Инвертировать объект или вернуть итератор, который итерируется в обратном порядке.

END_OF_DOCUMENT_MARKER
jinja-filters.round(value: float, precision: int = 0, method: 'te.Literal["common", "ceil", "floor"]' = 'common') → float

Округляет число до заданной точности. Первый параметр определяет точность (по умолчанию 0), второй — метод округления:

  • 'common' округляет вверх или вниз
  • 'ceil' всегда округляет вверх
  • 'floor' всегда округляет вниз

Если вы не укажете метод, используется 'common'.

{{ 42.55|round }}
    -> 43.0
{{ 42.55|round(1, 'floor') }}
    -> 42.5

Обратите внимание, что даже если округлять до 0 точности, возвращается число с плавающей точкой. Если вам нужен целое число, используйте фильтр int:

{{ 42.55|round|int }}
    -> 43
jinja-filters.safe(value: str) → markupsafe.Markup

Помечает значение как безопасное, что означает, что в среде с автоматическим экранированием эта переменная не будет экранирована.

jinja-filters.select(value: 't.Iterable[V]', *args: Any, **kwargs: Any) → 't.Iterator[V]'

Фильтры последовательность объектов, применяя тест к каждому объекту и выбирая только объекты, для которых тест выполняется.

Если тест не указан, каждый объект оценивается как булево значение.

Пример использования:

{{ numbers|select("odd") }}
{{ numbers|select("odd") }}
{{ numbers|select("divisibleby", 3) }}
{{ numbers|select("lessthan", 42) }}
{{ strings|select("equalto", "mystring") }}

Аналогично генераторному выражению:

(n for n in numbers if test_odd(n))
(n for n in numbers if test_divisibleby(n, 3))
Changelog

Введено в версии 2.7.

jinja-filters.selectattr(value: 't.Iterable[V]', *args: Any, **kwargs: Any) → 't.Iterator[V]'

Фильтры последовательность объектов, применяя тест к указанному атрибуту каждого объекта и выбирая только объекты, для которых тест выполняется.

Если тест не указан, значение атрибута будет вычислено как булево значение.

Пример использования:

{{ users|selectattr("is_active") }}
{{ users|selectattr("email", "none") }}

Аналогично генераторному выражению:

(u for user in users if user.is_active)
(u for user in users if test_none(user.email))
Changelog

Введено в версии 2.7.

jinja-filters.slice(value: 't.Collection[V]', slices: int, fill_with: 't.Optional[V]' = None) → 't.Iterator[t.List[V]]'

Нарезает итератор и возвращает список списков, содержащих элементы. Полезно, если вы хотите создать div, содержащий три тега ul, представляющие столбцы:

<div class="columnwrapper">
  {%- for column in items|slice(3) %}
    <ul class="column-{{ loop.index }}">
    {%- for item in column %}
      <li>{{ item }}</li>
    {%- endfor %}
    </ul>
  {%- endfor %}
</div>

Если вы передадите второй аргумент, он используется для заполнения пропущенных значений на последней итерации.

jinja-filters.sort(value: 't.Iterable[V]', reverse: bool = False, case_sensitive: bool = False, attribute: str | int | NoneType = None) → 't.List[V]'

Сортирует итерируемый объект с помощью функции Python sorted().

{% for city in cities|sort %}
    ...
{% endfor %}
Parameters:
  • reverse – Сортировать в порядке убывания вместо возрастания.
  • case_sensitive – При сортировке строк, сортировать прописные и строчные буквы по отдельности.
  • attribute – При сортировке объектов или словарей, атрибут или ключ для сортировки. Можно использовать нотацию точек, например "address.city". Может быть списком атрибутов, например "age,name".

Сортировка стабильна, относительный порядок элементов, которые сравниваются как равные, не меняется. Это позволяет выполнять цепочку сортировок по разным атрибутам и порядку.

{% for user in users|sort(attribute="name")
    |sort(reverse=true, attribute="age") %}
    ...
{% endfor %}

В качестве сокращения при цепочке, когда направление одинаково для всех атрибутов, передайте через запятую список атрибутов.

{% for user in users|sort(attribute="age,name") %}
    ...
{% endfor %}
Changelog

Изменено в версии 2.11.0: Параметр attribute может быть списком атрибутов, разделенных запятыми, например "age,name".

Изменено в версии 2.6: Добавлен параметр attribute.

jinja-filters.string(value)

Преобразует объект в строку, если он им не является. Это сохраняет строку Markup, а не преобразует её обратно в обычную строку, поэтому она всё ещё будет помечена как безопасная и не будет повторно экранирована.

>>> value = escape("<User 1>")
>>> value
Markup('&lt;User 1&gt;')
>>> escape(str(value))
Markup('&amp;lt;User 1&amp;gt;')
>>> escape(soft_str(value))
Markup('&lt;User 1&gt;')
jinja-filters.striptags(value: 't.Union[str, HasHTML]') → str

Удаляет теги SGML/XML и заменяет последовательные пробелы одним пробелом.

jinja-filters.sum(iterable: 't.Iterable[V]', attribute: str | int | NoneType = None, start: V = 0) → V

Возвращает сумму последовательности чисел плюс значение параметра 'start' (по умолчанию 0). Если последовательность пуста, возвращается значение start.

Также можно суммировать только определённые атрибуты:

Total: {{ items|sum(attribute='price') }}
Changelog

Изменено в версии 2.6: Добавлен параметр attribute для суммирования по атрибутам. Также параметр start перемещен вправо.

jinja-filters.title(s: str) → str

Возвращает значение в формате заголовка. То есть слова будут начинаться с заглавных букв, а все остальные символы — строчными.

jinja-filters.tojson(value: Any, indent: int | None = None) → markupsafe.Markup

Сериализует объект в строку JSON и помечает её как безопасную для рендеринга в HTML. Этот фильтр предназначен только для использования в HTML-документах.

Возвращаемая строка безопасна для рендеринга в HTML-документах и <script> тегах. Исключение составляют HTML-атрибуты с двойными кавычками; используйте одинарные кавычки или фильтр |forceescape.

Parameters:
  • value – Объект для сериализации в JSON.
  • indent – Параметр indent передаваемый в dumps, для красивой печати значения.
Changelog

Введено в версии 2.9.

jinja-filters.trim(value: str, chars: str | None = None) → str

Удаляет ведущие и хвостовые символы, по умолчанию — пробелы.

jinja-filters.truncate(s: str, length: int = 255, killwords: bool = False, end: str = '...', leeway: int | None = None) → str

Возвращает усеченную копию строки. Длина задается первым параметром, по умолчанию 255. Если второй параметр true, фильтр обрезает текст по длине. В противном случае отбрасывает последнее слово. Если текст был усечён, добавляет многоточие ("..."). Если вам нужно другое многоточие, чем "...", вы можете указать его, используя третий параметр. Строки, которые превышают длину только на допустимый предел, заданный в четвёртом параметре, не усекаются.

{{ "foo bar baz qux"|truncate(9) }}
    -> "foo..."
{{ "foo bar baz qux"|truncate(9, True) }}
    -> "foo ba..."
{{ "foo bar baz qux"|truncate(11) }}
    -> "foo bar baz qux"
{{ "foo bar baz qux"|truncate(11, False, '...', 0) }}
    -> "foo bar..."

По умолчанию, в более новых версиях Jinja, значение левого допуска — 5, а раньше оно было 0, но может быть переконфигурировано глобально.

jinja-filters.unique(value: 't.Iterable[V]', case_sensitive: bool = False, attribute: str | int | NoneType = None) → 't.Iterator[V]'

Возвращает список уникальных элементов из заданной итерируемой последовательности.

{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }}
    -> ['foo', 'bar', 'foobar']

Уникальные элементы выдаются в том же порядке, что и их первое появление в итерируемой последовательности, переданной в фильтр.

Parameters:
  • case_sensitive – Считать прописные и строчные буквы в строках как разные.
  • attribute – Фильтровать объекты с уникальными значениями для этого атрибута.
jinja-filters.upper(s: str) → str

Преобразовать значение в верхний регистр.

jinja-filters.urlencode(value: str | Mapping[str, Any] | Iterable[Tuple[str, Any]]) → str

Кодировать данные для использования в пути или запросе URL с использованием UTF-8.

Базовый обертка над urllib.parse.quote() при передаче строки или urllib.parse.urlencode() для словаря или итерируемого объекта.

Parameters:

value – Данные для кодирования. Строка будет закодирована напрямую. Словарь или итерируемый объект пар (key, value) будут объединены как строка запроса.

При передаче строки, “/” не кодируется. Веб-серверы обрабатывают “/” и “%2F” в путях как эквивалентные. Если вам нужны кодированные слэши, используйте фильтр |replace("/", "%2F").

Changelog

Введено в версии 2.7.

END_OF_DOCUMENT_MARKER
jinja-filters.urlize(value: str, trim_url_limit: int | None = None, nofollow: bool = False, target: str | None = None, rel: str | None = None, extra_schemes: Iterable[str] | None = None) → str

Преобразовать URL-адреса в тексте в нажимаемые ссылки.

Возможно, ссылки в некоторых ситуациях не будут распознаны. Обычно лучше использовать более полный форматировщик, например, библиотеку Markdown.

Работает с http://, https://, www., mailto:, и адресами электронной почты. Ссылки с заключительной пунктуацией (точки, запятые, закрывающие скобки) и начальной пунктуацией (открывающие скобки) распознаются, исключая пунктуацию. Адреса электронной почты, содержащие заголовки, не распознаются (например, mailto:address@example.com?cc=copy@example.com).

Параметры:
  • value – Исходный текст, содержащий URL-адреса, которые нужно связать.
  • trim_url_limit – Укоротить отображаемые значения URL до указанной длины.
  • nofollow – Добавить атрибут rel=nofollow к ссылкам.
  • target – Добавить атрибут target к ссылкам.
  • rel – Добавить атрибут rel к ссылкам.
  • extra_schemes – Распознавать URL-адреса, начинающиеся с этих схем помимо стандартного поведения. По умолчанию env.policies["urlize.extra_schemes"], что по умолчанию означает отсутствие дополнительных схем.
Журнал изменений

Изменено в версии 3.0: Добавлен параметр extra_schemes.

Изменено в версии 3.0: Генерировать ссылки https:// для URL-адресов без схемы.

Изменено в версии 3.0: Правила разбора были обновлены. Распознавать адреса электронной почты с или без схемы mailto:. Проверять IP-адреса. Игнорировать скобки и квадратные скобки в большем количестве случаев.

Изменено в версии 2.8: Добавлен параметр target.

jinja-filters.wordcount(s: str) → int

Подсчитать слова в строке.

jinja-filters.wordwrap(s: str, width: int = 79, break_long_words: bool = True, wrapstring: str | None = None, break_on_hyphens: bool = True) → str

Разбить строку на строки заданной ширины. Существующие переводы строк обрабатываются как абзацы, которые нужно разбивать отдельно.

Параметры:
  • s – Исходный текст для разбиения.
  • width – Максимальная длина строк после разбиения.
  • break_long_words – Если слово длиннее width, разбить его на несколько строк.
  • break_on_hyphens – Если слово содержит дефисы, его можно разбить на строки.
  • wrapstring – Строка для объединения каждой строки после разбиения. По умолчанию Environment.newline_sequence.
Журнал изменений

Изменено в версии 2.11: Существующие переводы строк обрабатываются как абзацы, которые нужно разбивать отдельно.

Изменено в версии 2.11: Добавлен параметр break_on_hyphens.

Изменено в версии 2.7: Добавлен параметр wrapstring.

jinja-filters.xmlattr(d: Mapping[str, Any], autospace: bool = True) → str

Создать строку атрибутов SGML/XML на основе элементов в словаре. Все значения, которые не являются none или undefined, автоматически экранируются:

<ul{{ {'class': 'my_list', 'missing': none,
        'id': 'list-%d'|format(variable)}|xmlattr }}>
...
</ul>

Результат, например:

<ul class="my_list" id="list-42">
...
</ul>

Как видно, перед элементом автоматически добавляется пробел, если фильтр вернул что-либо, за исключением случая, когда второй параметр false.

END_OF_DOCUMENT_MARKER

Список встроенных тестов

boolean()

even()

in()

mapping()

sequence()

callable()

false()

integer()

ne()

string()

defined()

filter()

iterable()

none()

test()

divisibleby()

float()

le()

number()

true()

eq()

ge()

lower()

odd()

undefined()

escaped()

gt()

lt()

sameas()

upper()

jinja-tests.boolean(value: Any) → bool

Возвращает True, если объект является булевым значением.

Журнал изменений

Введено в версии 2.11.

jinja-tests.callable(obj, /)

Возвращает, является ли объект вызываемым (т.е. некоторой функцией).

Обратите внимание, что классы вызываемы, так же как и экземпляры классов с методом __call__().

jinja-tests.defined(value: Any) → bool

Возвращает True, если переменная определена:

{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

См. фильтр default() для простого способа установки неопределённых переменных.

jinja-tests.divisibleby(value: int, num: int) → bool

Проверяет, делится ли переменная на число без остатка.

jinja-tests.eq(a, b, /)

То же самое, что и a == b.

Псевдонимы:

==, equalto

jinja-tests.escaped(value: Any) → bool

Проверить, экранировано ли значение.

jinja-tests.even(value: int) → bool

Возвращает True, если переменная чётная.

jinja-tests.false(value: Any) → bool

Возвращает True, если объект равен False.

Журнал изменений

Введено в версии 2.11.

jinja-tests.filter(value: str) → bool

Проверить, существует ли фильтр по имени. Полезно, если фильтр может быть необязательно доступен.

{% if 'markdown' is filter %}
    {{ value | markdown }}
{% else %}
    {{ value }}
{% endif %}
Журнал изменений

Введено в версии 3.0.

jinja-tests.float(value: Any) → bool

Возвращает True, если объект является числом с плавающей точкой.

Журнал изменений

Введено в версии 2.11.

jinja-tests.ge(a, b, /)

То же самое, что и a >= b.

Псевдонимы:

>=

jinja-tests.gt(a, b, /)

То же самое, что и a > b.

Псевдонимы:

>, greaterthan

jinja-tests.in(value: Any, seq: Container) → bool

Проверить, есть ли значение в seq.

Журнал изменений

Введено в версии 2.10.

jinja-tests.integer(value: Any) → bool

Возвращает True, если объект является целым числом.

Журнал изменений

Введено в версии 2.11.

jinja-tests.iterable(value: Any) → bool

Проверка возможности итерирования по объекту.

jinja-tests.le(a, b, /)

То же самое, что и a <= b.

Псевдонимы:

<=

jinja-tests.lower(value: str) → bool

Возвращает True, если переменная в нижнем регистре.

jinja-tests.lt(a, b, /)

То же самое, что и a < b.

Псевдонимы:

<, lessthan

jinja-tests.mapping(value: Any) → bool

Возвращает True, если объект является отображением (например, dict).

Журнал изменений

Введено в версии 2.6.

jinja-tests.ne(a, b, /)

То же самое, что и a != b.

Псевдонимы:

!=

jinja-tests.none(value: Any) → bool

Возвращает True, если переменная равна None.

jinja-tests.number(value: Any) → bool

Возвращает True, если переменная является числом.

jinja-tests.odd(value: int) → bool

Возвращает True, если переменная нечётная.

jinja-tests.sameas(value: Any, other: Any) → bool

Проверить, ссылается ли объект на тот же адрес памяти, что и другой объект:

{% if foo.attribute is sameas false %}
    the foo attribute really is the `False` singleton
{% endif %}
jinja-tests.sequence(value: Any) → bool

Возвращает True, если переменная является последовательностью. Последовательности — это итерируемые переменные.

jinja-tests.string(value: Any) → bool

Возвращает True, если объект является строкой.

jinja-tests.test(value: str) → bool

Проверить, существует ли тест по имени. Полезно, если тест может быть необязательно доступен.

{% if 'loud' is test %}
    {% if value is loud %}
        {{ value|upper }}
    {% else %}
        {{ value|lower }}
    {% endif %}
{% else %}
    {{ value }}
{% endif %}
Журнал изменений

Введено в версии 3.0.

jinja-tests.true(value: Any) → bool

Возвращает True, если объект равен True.

Журнал изменений

Введено в версии 2.11.

jinja-tests.undefined(value: Any) → bool

Аналогично defined(), но наоборот.

jinja-tests.upper(value: str) → bool

Возвращает True, если переменная в верхнем регистре.

END_OF_DOCUMENT_MARKER

Список глобальных функций

По умолчанию доступны следующие функции в глобальной области видимости:

jinja-globals.range([start, ]stop[, step])

Возвращает список, содержащий арифметическую прогрессию целых чисел. range(i, j) возвращает [i, i+1, i+2, ..., j-1]; start (!) по умолчанию 0. Когда step задан, он определяет шаг (или убывание). Например, range(4) и range(0, 4, 1) возвращают [0, 1, 2, 3]. Конечная точка опущена! Это точно те индексы, которые допустимы для списка из 4 элементов.

Это полезно для многократного повторения блока шаблона, например, для заполнения списка. Представьте, что у вас 7 пользователей в списке, но вы хотите отобразить три пустых элемента, чтобы принудительно задать высоту с помощью CSS:

<ul>
{% for user in users %}
    <li>{{ user.username }}</li>
{% endfor %}
{% for number in range(10 - users|count) %}
    <li class="empty"><span>...</span></li>
{% endfor %}
</ul>
jinja-globals.lipsum(n=5, html=True, min=20, max=100)

Генерирует лорем-ипсум для шаблона. По умолчанию генерируются пять абзацев HTML, при этом каждый абзац содержит от 20 до 100 слов. Если html равен False, возвращается обычный текст. Это полезно для генерации простого контента для тестирования макета.

jinja-globals.dict(\**items)

Удобная альтернатива литералам dict. {'foo': 'bar'} равно dict(foo='bar').

class jinja-globals.cycler(\*items)

Циклически проход через значения, вызывая их по одному, затем перезапускается, когда достигается конец.

Аналогично loop.cycle, но может использоваться вне циклов или через несколько циклов. Например, отобразите список папок и файлов в списке, чередуя им классы «нечетный» и «четный».

{% set row_class = cycler("odd", "even") %}
<ul class="browser">
{% for folder in folders %}
  <li class="folder {{ row_class.next() }}">{{ folder }}
{% endfor %}
{% for file in files %}
  <li class="file {{ row_class.next() }}">{{ file }}
{% endfor %}
</ul>
Параметры:

items – Каждый позиционный аргумент будет выводиться в заданном порядке для каждого цикла.

Журнал изменений

Новая функция в версии 2.1.

property current

Возвращает текущий элемент. Эквивалентно элементу, который будет возвращен в следующий раз, когда вызовется next().

next()

Возвращает текущий элемент, затем переводит current на следующий элемент.

reset()

Сбрасывает текущий элемент до первого элемента.

class jinja-globals.joiner(sep=', ')

Небольшой помощник, который можно использовать для «соединения» нескольких разделов. Соединитель получает строку и возвращает эту строку каждый раз, когда он вызывается, кроме первого (в этом случае он возвращает пустую строку). Вы можете использовать это для объединения вещей:

{% set pipe = joiner("|") %}
{% if categories %} {{ pipe() }}
    Categories: {{ categories|join(", ") }}
{% endif %}
{% if author %} {{ pipe() }}
    Author: {{ author() }}
{% endif %}
{% if can_edit %} {{ pipe() }}
    <a href="?action=edit">Edit</a>
{% endif %}
Журнал изменений

Новая функция в версии 2.1.

class jinja-globals.namespace(...)

Создает новый контейнер, который позволяет присваивать атрибуты с помощью тега {% set %}:

{% set ns = namespace() %}
{% set ns.foo = 'bar' %}

Основная цель этого — позволить передавать значение из тела цикла во внешнюю область видимости. Начальные значения могут быть предоставлены как словарь, как ключевые аргументы или оба (то же поведение, что и у конструктора Python dict):

{% set ns = namespace(found=false) %}
{% for item in items %}
    {% if item.check_something() %}
        {% set ns.found = true %}
    {% endif %}
    * {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
Журнал изменений

Новая функция в версии 2.10.

Расширения

В следующих разделах рассматриваются встроенные расширения Jinja, которые могут быть включены приложением. Приложение также может предоставить дополнительные расширения, не охваченные этим документом; в этом случае должен быть отдельный документ, объясняющий указанные расширения.

Международная поддержка локализации

Если расширение i18n включено, можно пометить текст в шаблоне как переводящийся. Для того, чтобы пометить раздел как переводящийся, используйте блок trans:

{% trans %}Hello, {{ user }}!{% endtrans %}

Внутри блока не допускаются операторы, только текст и простые переменные теги.

Теги переменных могут быть только именем, не доступом к атрибутам, фильтрам или другим выражениям. Для использования выражения, привяжите его к имени в теге trans для использования в блоке.

{% trans user=user.username %}Hello, {{ user }}!{% endtrans %}

Чтобы привязать более одного выражения, разделяйте их запятыми (,).

{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}

Для множественного числа укажите оба варианта, единственное и множественное число, разделенные тегом pluralize.

{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}

По умолчанию, первая переменная в блоке используется для определения того, следует ли использовать единственное или множественное число. Если это неверно, укажите переменную, используемую для множественного числа, в качестве параметра pluralize.

{% trans ..., user_count=users|length %}...
{% pluralize user_count %}...{% endtrans %}

При переводе блоков текста пробелы и переводы строк приводят к трудночитаемым и склонным к ошибкам строкам перевода. Чтобы избежать этого, блок trans можно пометить как обрезной, что заменит все переводы строк и пробелы вокруг них одним пробелом и удалит начальные и конечные пробелы.

{% trans trimmed book_title=book.title %}
    This is {{ book_title }}.
    You should read it!
{% endtrans %}

Это приведет к This is %(book_title)s. You should read it! в файле перевода.

Если обрезка включена глобально, модификатор notrimmed можно использовать для отключения ее для блока.

Журнал изменений

Новое в версии 2.10: Добавлены модификаторы trimmed и notrimmed.

Если перевод зависит от контекста, в котором появляется сообщение, функции pgettext и npgettext принимают строку контекста в качестве первого аргумента, которая используется для выбора соответствующего перевода. Для указания контекста с помощью тега {% trans %}, укажите строку в качестве первого токена после trans.

{% trans "fruit" %}apple{% endtrans %}
{% trans "fruit" trimmed count -%}
    1 apple
{%- pluralize -%}
    {{ count }} apples
{%- endtrans %}

Новое в версии 3.1: Контекст может быть передан в тег trans для использования pgettext и npgettext.

Можно переводить строки в выражениях с помощью этих функций:

  • _(message): Псевдоним для gettext.
  • gettext(message): Перевести сообщение.
  • ngettext(singluar, plural, n): Перевести сообщение в единственном или множественном числе на основе переменной количества.
  • pgettext(context, message): Как gettext(), но выбирает перевод на основе строки контекста.
  • npgettext(context, singular, plural, n): Как npgettext(), но выбирает перевод на основе строки контекста.

Можно вывести переведенную строку так:

{{ _("Hello, World!") }}

Для использования заменителей используйте фильтр format.

{{ _("Hello, %(user)s!")|format(user=user.username) }}

Всегда используйте ключевые аргументы для format, так как другие языки могут не использовать слова в том же порядке.

Если вызовы New Style Gettext активированы, использование заменителей упрощается. Форматирование является частью вызова gettext вместо использования фильтра format.

{{ gettext('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}
{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}

Строка форматирования функции ngettext автоматически получает счетчик как параметр num в дополнение к заданным параметрам.

Оператор выражения

Если загружено расширение оператора выражения, доступен тег do, который работает точно так же, как обычное выражение переменной ({{ ... }}); за исключением того, что он ничего не выводит. Это можно использовать для изменения списков:

{% do navigation.append('a string') %}

Управление циклами

Если приложение включает Управление циклами, можно использовать break и continue в циклах. Когда достигается break, цикл завершается; если достигается continue, обработка останавливается и продолжается с следующей итерацией.

Вот цикл, который пропускает каждый второй элемент:

{% for user in users %}
    {%- if loop.index is even %}{% continue %}{% endif %}
    ...
{% endfor %}

Аналогично, цикл, который останавливает обработку после 10-й итерации:

{% for user in users %}
    {%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}

Обратите внимание, что loop.index начинается с 1, а loop.index0 начинается с 0 (см.: For).

Оператор отладки

Если включено расширение Отладка, тег {% debug %} будет доступен для вывода текущего контекста, а также доступных фильтров и тестов. Это полезно для того, чтобы увидеть, что доступно для использования в шаблоне, не настраивая отладчик.

<pre>{% debug %}</pre>
{'context': {'cycler': <class 'jinja2.utils.Cycler'>,
             ...,
             'namespace': <class 'jinja2.utils.Namespace'>},
 'filters': ['abs', 'attr', 'batch', 'capitalize', 'center', 'count', 'd',
             ..., 'urlencode', 'urlize', 'wordcount', 'wordwrap', 'xmlattr'],
 'tests': ['!=', '<', '<=', '==', '>', '>=', 'callable', 'defined',
           ..., 'odd', 'sameas', 'sequence', 'string', 'undefined', 'upper']}

Оператор with

Журнал изменений

Новое в версии 2.3.

Оператор with позволяет создавать новую внутреннюю область видимости. Переменные, установленные в этой области видимости, не видны за пределами области видимости.

Оператор with вкратце:

{% with %}
    {% set foo = 42 %}
    {{ foo }}           foo is 42 here
{% endwith %}
foo is not visible here any longer

Поскольку обычно переменные устанавливаются в начале области видимости, вы можете сделать это в операторе with. Следующие два примера эквивалентны:

{% with foo = 42 %}
    {{ foo }}
{% endwith %}

{% with %}
    {% set foo = 42 %}
    {{ foo }}
{% endwith %}

Важное замечание по области видимости. В версиях Jinja до 2.9 поведение ссылки одной переменной на другую имело некоторые непреднамеренные последствия. В частности, одна переменная могла ссылаться на другую, определенную в том же открывающем операторе блока with. Это создавало проблемы с поведением области видимости, и с тех пор это было улучшено. В частности, в более новых версиях Jinja следующий код всегда ссылается на переменную a вне блока with:

{% with a={}, b=a.attribute %}...{% endwith %}

В более ранних версиях Jinja атрибут b ссылался на результаты первого атрибута. Если вы зависите от этого поведения, вы можете переписать его, чтобы использовать тег set:

{% with a={} %}
    {% set b = a.attribute %}
{% endwith %}

Расширение

В более старых версиях Jinja (до 2.9) для включения этой функции требовалось расширение. Теперь он включен по умолчанию.

Переопределения автоэкранирования

Журнал изменений

Новое в версии 2.4.

Если нужно, вы можете активировать и деактивировать автоэкранирование прямо в шаблонах.

Пример:

{% autoescape true %}
    Autoescaping is active within this block
{% endautoescape %}

{% autoescape false %}
    Autoescaping is inactive within this block
{% endautoescape %}

После endautoescape поведение возвращается к тому, что было до этого.

Расширение

В более ранних версиях Jinja (до 2.9) для включения этой функции требовалось расширение. Теперь она включена по умолчанию.

© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/3.1.x/templates/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API