Документация шаблонизатора
Этот документ описывает синтаксис и семантику движка шаблонов и будет наиболее полезен в качестве справочника для разработчиков шаблонов 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 настроены следующим образом:
-
{% ... %}для Операторов -
{{ ... }}для Выражений для вывода в шаблон -
{# ... #}для Комментарии, которые не включаются в вывод шаблона -
# ... ##для Операторы на строках
Переменные
Переменные шаблона определяются словарем контекста, переданным в шаблон.
Вы можете использовать переменные в шаблонах, при условии, что они переданы приложением. Переменные могут иметь атрибуты или элементы, к которым вы можете получить доступ. Какие атрибуты у переменной, сильно зависит от приложения, предоставляющего эту переменную.
Вы можете использовать точку (.) для доступа к атрибутам переменной, помимо стандартного синтаксиса Python __getitem__ «индексации» ([]).
Следующие строки делают то же самое:
{{ foo.bar }}
{{ foo['bar'] }}
Важно знать, что внешние двойные фигурные скобки не являются частью переменной, а частью оператора вывода. Если вы обращаетесь к переменным внутри тегов, не ставьте фигурных скобок вокруг них.
Если переменная или атрибут не существует, вы получите неопределённое значение. Что вы можете сделать с таким значением, зависит от конфигурации приложения: стандартное поведение — выводить пустую строку при выводе или итерации, и отказывать для всех других операций.
Реализация
Для удобства, foo.bar в Jinja2 выполняет следующие действия на уровне 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>
Вы также можете удалить пробелы в шаблонах вручную. Если вы добавите минус (-) в начало или конец блока (например, тега Цикла), комментария или выражения переменной, пробелы до или после этого блока будут удалены:
{% for item in seq -%}
{{ item }}
{%- endfor %}
Это даст все элементы без пробелов между ними. Если seq был списком чисел от 1 до 9, вывод был бы 123456789.
Если операторы на строках включены, они автоматически удаляют начальные пробелы до начала строки.
По умолчанию Jinja2 также удаляет заключительные символы новой строки. Чтобы сохранить одну заключительную новую строку, настройте Jinja на keep_trailing_newline.
Примечание
Вы не должны добавлять пробелы между тегом и знаком минус.
вариант 1:
{%- if foo -%}...{% endif %}
неверный вариант:
{% - if foo - %}...{% endif %}
Экранирование
Иногда желательно — даже необходимо — заставить Jinja игнорировать части, которые он иначе обрабатывает как переменные или блоки. Например, если с помощью стандартного синтаксиса вы хотите использовать {{ как строку без обработки в шаблоне и не начинать переменную, вам нужно применить уловку.
Самый простой способ вывести разделитель переменной ({{) — использовать выражение переменной:
{{ '{{' }}
Для больших блоков имеет смысл отметить блок raw. Например, чтобы включить синтаксис Jinja в шаблон, можно использовать этот фрагмент:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
Операторы на строках
Если операторы на строках включены приложением, можно пометить строку как оператор. Например, если префикс для операторов на строках настроен на #, следующие два примера эквивалентны:
<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 %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
В этом примере теги {% block %} определяют четыре блока, которые могут заполняться дочерними шаблонами. Все, что делает тег block, — это сообщает движку шаблонов, что дочерний шаблон может переопределить эти заполнители в шаблоне.
Дочерний шаблон
Дочерний шаблон может выглядеть так:
{% 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-Master 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 %}
Именованные теги завершения блока
Jinja2 позволяет помещать имя блока после тега завершения для лучшей читаемости:
{% 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 не нужно указывать.
Объекты шаблонов
Changelog
Изменено в версии 2.4.
Если в контексте шаблона был передан объект шаблона, вы также можете расширить его. Предполагая, что вызывающий код передаёт макет шаблона как layout_template в среду, этот код работает:
{% extends layout_template %}
Ранее переменная layout_template должна была быть строкой с именем файла макета шаблона для работы этого кода.
Выполнение HTML-экранирования
При генерации HTML из шаблонов всегда существует риск, что переменная будет содержать символы, влияющие на полученный HTML. Существует два подхода:
- ручное экранирование каждой переменной; или
- автоматическое экранирование всего по умолчанию.
Jinja поддерживает оба варианта. Какой используется, зависит от конфигурации приложения. Конфигурация по умолчанию — это отсутствие автоматического экранирования; по разным причинам:
- Экранирование всего, кроме безопасных значений, также означает, что Jinja экранирует переменные, известные как не содержащие HTML (например, числа, булевы значения), что может значительно снизить производительность.
- Информация о безопасности переменной очень хрупкая. Может случиться, что при приведении безопасных и небезопасных значений возвращаемое значение будет заэкранировано дважды.
Работа с ручным экранированием
Если ручное экранирование включено, вы необходимости должны экранировать переменные при необходимости. Что экранировать? Если у вас есть переменная, которая может содержать любой из следующих символов (>, <, &, или "), вы должны экранировать её, если переменная не содержит правильно сформированный и надёжный HTML. Экранирование выполняется путём передачи переменной через фильтр |e.
{{ user.username|e }}
Работа с автоматическим экранированием
При включенном автоматическом экранировании всё экранируется по умолчанию, за исключением значений, явно помеченных как безопасные. Переменные и выражения могут быть помечены как безопасные в:
- словаре контекста приложением с помощью
markupsafe.Markup, или - в шаблоне, с помощью фильтра
|safe
Основная проблема с этим подходом заключается в том, что сам Python не имеет понятия о «заражённых» значениях; поэтому информация о том, является ли значение безопасным или небезопасным, может быть потеряна.
Если значение не помечено как безопасное, будет выполнено автоматическое экранирование; это может привести к двойному экранированию содержимого. Однако избежать двойного экранирования легко: просто используйте инструменты, предоставляемые Jinja2, и не используйте встроенные конструкции Python, такие как str.format или оператор модуля строк (%).
Функции Jinja2 (макросы, super, self.BLOCKNAME) всегда возвращают данные шаблонов, помеченные как безопасные.
Строковые литералы в шаблонах с автоматическим экранированием считаются небезопасными, потому что собственные строки Python (str, unicode, basestring) не являются строками markupsafe.Markup с атрибутом __html__.
Список управляющих структур
Управляющая структура относится ко всем элементам, которые контролируют поток программы: условные конструкции (т.е. 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 не упорядочены; поэтому вы можете либо передать отсортированный list из tuple — или collections.OrderedDict — в шаблон, либо использовать фильтр dictsort.
Внутри цикла for можно получить доступ к некоторым специальным переменным:
Переменная | Описание |
|---|---|
| Текущая итерация цикла. (индексировано с 1) |
| Текущая итерация цикла. (индексировано с 0) |
| Номер итераций с конца цикла (индексировано с 1) |
| Номер итераций с конца цикла (индексировано с 0) |
| Истина, если это первая итерация. |
| Истина, если это последняя итерация. |
| Количество элементов в последовательности. |
| Вспомогательная функция для циклического перебора списка последовательностей. См. объяснение ниже. |
| Указывает глубину вложенности цикла. Начинается с уровня 1 |
| Указывает глубину вложенности цикла. Начинается с уровня 0 |
| Элемент из предыдущей итерации цикла. Не определено во время первой итерации. |
| Элемент из следующей итерации цикла. Не определено во время последней итерации. |
| Истина, если ранее вызывался с другим значением (или не вызывался вообще). |
Внутри цикла 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(…) }}
Обратите внимание, что присваивания в циклах будут очищаться в конце итерации и не смогут существовать дольше области видимости цикла. Более ранние версии Jinja2 имели ошибку, из-за которой в некоторых случаях казалось, что присваивания работают. Это не поддерживается. См. Присваивания для получения дополнительной информации о том, как с этим справиться.
Если все, что вам нужно сделать, это проверить, изменилось ли некоторое значение с последней итерации или изменится на следующей итерации, вы можете использовать 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 в 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 %}
Если также может использоваться как встроенное выражение и для фильтрации цикла.
Макросы
Макросы аналогичны функциям в обычных языках программирования. Они полезны для помещения часто используемых выражений в переиспользуемые функции, чтобы не повторяться («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 -
Если макрос был вызван из тега call, вызывающий элемент хранится в этой переменной как вызываемый макрос.
Макросы также предоставляют доступ к некоторым внутренним данным. Доступны следующие атрибуты объекта макроса:
-
name -
Имя макроса.
{{ input.name }}выведетinput. -
arguments -
Кортеж имён аргументов, которые принимает макрос.
-
defaults -
Кортеж значений по умолчанию.
-
catch_kwargs -
Это
true, если макрос принимает дополнительные именованные аргументы (т.е. использует специальную переменнуюkwargs). -
catch_varargs -
Это
true, если макрос принимает дополнительные позиционные аргументы (т.е. использует специальную переменнуюvarargs). -
caller -
Это
true, если макрос использует специальную переменнуюcallerи может вызываться из тега call.
Если имя макроса начинается с нижнего подчёркивания, он не экспортируется и не может быть импортирован.
Вызов
В некоторых случаях может быть полезно передать макрос другому макросу. Для этого можно использовать специальный блок 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>
<dl>Realname</dl>
<dd>{{ user.realname|e }}</dd>
<dl>Description</dl>
<dd>{{ user.description }}</dd>
</dl>
{% endcall %}
Фильтры
Секции фильтров позволяют применять стандартные фильтры Jinja2 к блоку данных шаблона. Просто оберните код в специальную секцию filter:
{% filter upper %}
This text becomes uppercase
{% 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 разрешена только для объектов пространства имен; попытка присвоить атрибут любому другому объекту вызовет исключение.
Changelog
Добавлено в версии 2.10: Добавлена поддержка объектов пространства имен
Блочные присваивания
Changelog
Добавлено в версии 2.8.
Начиная с Jinja 2.8, можно также использовать блочные присваивания для захвата содержимого блока в переменную. Это может быть полезно в некоторых ситуациях как альтернатива макросам. В этом случае, вместо использования знака равенства и значения, вы просто записываете имя переменной, а затем всё до {% endset %} включительно будет захвачено.
Пример:
{% set navigation %}
<li><a href="/">Index</a>
<li><a href="/downloads">Downloads</a>
{% endset %}
Переменная navigation тогда содержит исходный HTML-код навигации.
Changelog
Изменено в версии 2.10.
Начиная с Jinja 2.10, блочные присваивания поддерживают фильтры.
Пример:
{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}
Расширение
Тег extends используется для расширения одного шаблона из другого. В файле может быть несколько тегов extends , но только один из них может быть выполнен в одно время.
См. раздел о Наследовании шаблонов выше.
Блоки
Блоки используются для наследования и служат как заглушками, так и заменами. Они подробно описаны в разделе Наследование шаблонов.
Включение
Инструкция include полезна для включения шаблона и возвращения отрендеренного содержимого этого файла в текущее пространство имен:
{% include 'header.html' %}
Body
{% include 'footer.html' %}
Включённые шаблоны по умолчанию имеют доступ к переменным активного контекста. Более подробную информацию о поведении контекста импорта и включения см. в разделе Поведение контекста импорта.
Начиная с Jinja 2.2, можно отметить включение с ignore missing; в этом случае Jinja проигнорирует инструкцию, если включаемый шаблон не существует. В сочетании с with или without context, его необходимо поместить перед указанием видимости контекста. Вот несколько допустимых примеров:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
Changelog
Добавлено в версии 2.2.
Можно также указать список шаблонов, которые проверяются на существование перед включением. Первый существующий шаблон будет включён. Если ignore missing предоставлен, он вернётся к ничего не рендерингу, если ни один из шаблонов не существует; в противном случае вызовет исключение.
Пример:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
Changelog
Изменено в версии 2.4: Если объект шаблона был передан в контекст шаблона, вы можете включить этот объект, используя include.
Импорт
Jinja2 поддерживает размещение часто используемого кода в макросах. Эти макросы могут находиться в разных шаблонах и импортироваться оттуда. Это работает аналогично операторам import в 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>
Макросы и переменные, начинающиеся с одного или нескольких символов нижнего подчёркивания, являются закрытыми и не могут быть импортированы.
Changelog
Изменено в версии 2.4: Если объект шаблона был передан в контекст шаблона, вы можете импортировать из этого объекта.
Поведение контекста импорта
По умолчанию включённым шаблонам передаётся текущий контекст, а импортированным — нет. Причина в том, что импорты, в отличие от включений, кэшируются; импорты часто используются просто как модуль, содержащий макросы.
Это поведение можно изменить явно: добавив with context или without context к директиве импорта/включения, текущий контекст может быть передан шаблону, а кэширование автоматически отключено.
Вот два примера:
{% 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 может получить к нему доступ.
Выражения
Jinja позволяет использовать базовые выражения повсюду. Они работают очень похоже на стандартный Python; даже если вы не работаете с Python, вы должны чувствовать себя комфортно.
Литералы
Самой простой формой выражений являются литералы. Литералы представляют собой представления объектов Python, таких как строки и числа. Существуют следующие литералы:
- “Hello World”:
-
Всё между двумя двойными или одинарными кавычками — это строка. Они полезны всякий раз, когда вам нужна строка в шаблоне (например, в качестве аргументов для вызовов функций и фильтров или просто для расширения или включения шаблона).
- 42 / 42.23:
-
Целые и числа с плавающей запятой создаются путём простого написания числа. Если присутствует точка, число является числом с плавающей запятой, в противном случае целым числом. Имейте в виду, что в Python
42и42.0отличаются (intиfloat, соответственно). - [‘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.
Сравнения
- ==
-
Сравнивает два объекта на равенство.
- !=
-
Сравнивает два объекта на неравенство.
- >
-
trueесли левая часть больше правой. - >=
-
trueесли левая часть больше или равна правой.
- <
-
trueесли левая часть меньше правой. - <=
-
trueесли левая часть меньше или равна правой.
Логика
Для if утверждений, for фильтрации и if выражений может быть полезно объединить несколько выражений:
- and
-
Возвращает true, если левый и правый операнды — true.
- or
-
Возвращает true, если левый или правый операнды — true.
- 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
-
Выполняет тест.
- |
-
Применяет фильтр.
- ~
-
Преобразует все операнды в строки и конкатенирует их.
{{ "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 'master.html' %}
Общая синтаксис: <do something> if <something is true> else <do
something else>.
Часть else необязательна. Если она не указана, блок else неявно оценивается как неопределённый объект:
{{ "[{}]".format(page.title) if page.title }}
Методы Python
Вы также можете использовать любые методы, определённые для типа переменной. Возвращаемое значение вызова метода используется в качестве значения выражения. Вот пример, использующий методы, определённые для строк (где page.title — это строка):
{{ page.title.capitalize() }}
Это также работает для методов пользовательских типов. Например, если переменная f типа Foo имеет метод bar, вы можете сделать следующее:
{{ f.bar() }}
Список встроенных фильтров
-
abs(x, /) -
Возвращает абсолютное значение аргумента.
-
attr(obj, name) -
Получает атрибут объекта.
foo|attr("bar")работает какfoo.bar, за исключением того, что всегда возвращается атрибут, а элементы не ищутся.См. Примечания по подпискам для получения более подробной информации.
-
batch(value, linecount, fill_with=None) -
Фильтр, который группирует элементы. Он работает практически так же, как
slice, только в обратном порядке. Он возвращает список списков с заданным количеством элементов. Если вы предоставите второй параметр, он используется для заполнения недостающих элементов. Посмотрите этот пример:<table> {%- for row in items|batch(3, ' ') %} <tr> {%- for column in row %} <td>{{ column }}</td> {%- endfor %} </tr> {%- endfor %} </table>
-
capitalize(s) -
Преобразует значение в верхний регистр. Первый символ будет заглавным, остальные - строчными.
-
center(value, width=80) -
Выравнивает значение по центру в поле заданной ширины.
-
default(value, default_value='', boolean=False) -
Если значение не определено, возвращает переданное значение по умолчанию, иначе значение переменной:
{{ my_variable|default('my_variable is not defined') }}Это выведет значение
my_variable, если переменная была определена, иначе'my_variable is not defined'. Если вы хотите использовать default с переменными, которые оцениваются как ложь, вы должны установить второй параметр вtrue:{{ ''|default('the string was empty', true) }}Изменено в версии 2.11: Теперь можно настроить
EnvironmentсChainableUndefinedдля работы фильтраdefaultс вложенными элементами и атрибутами, которые могут содержать неопределенные значения в цепочке, без полученияUndefinedError.- Псевдонимы
-
d
-
dictsort(value, case_sensitive=False, by='key', reverse=False) -
Сортирует словарь и возвращает пары (ключ, значение). Поскольку словари Python не отсортированы, вы можете использовать эту функцию для их упорядочения по ключу или значению:
{% for item in mydict|dictsort %} sort the dict by key, case insensitive {% for item in mydict|dictsort(reverse=true) %} sort the dict by key, case insensitive, reverse order {% for item in mydict|dictsort(true) %} sort the dict by key, case sensitive {% for item in mydict|dictsort(false, 'value') %} sort the dict by value, case insensitive
-
escape(s) -
Преобразует символы &, <, >, ‘ и ” в строке s в безопасные для HTML последовательности. Используйте это, если вам нужно отобразить текст, который может содержать такие символы в HTML. Помечает возвращаемое значение как строку разметки.
- Псевдонимы
-
e
-
filesizeformat(value, binary=False) -
Форматирует значение как «человекочитаемый» размер файла (например, 13 КБ, 4,1 МБ, 102 байта и т. д.). По умолчанию используются десятичные префиксы (мега, гига и т. д.), если второй параметр установлен в
True, используются двоичные префиксы (меби, гиби).
-
first(seq) -
Возвращает первый элемент последовательности.
-
float(value, default=0.0) -
Преобразует значение в число с плавающей запятой. Если преобразование не удаётся, возвращает
0.0. Вы можете переопределить это значение по умолчанию, используя первый параметр.
-
forceescape(value) -
Принудительно выполняет экранирование HTML. Вероятно, это удваивает экранирование переменных.
-
format(value, *args, **kwargs) -
Применяет заданные значения к строке формата в стиле printf, как
string % values.{{ "%s, %s!"|format(greeting, name) }} Hello, World!В большинстве случаев будет удобнее и эффективнее использовать оператор
%илиstr.format().{{ "%s, %s!" % (greeting, name) }} {{ "{}, {}!".format(greeting, name) }}
-
groupby(value, attribute) -
Группирует последовательность объектов по атрибуту, используя функцию Python
itertools.groupby(). Атрибут может использовать нотацию точек для вложенного доступа, например,"address.city". В отличие от Python’sgroupby, значения сортируются сначала, поэтому для каждого уникального значения возвращается только одна группа.Например, список объектов
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), которые могут быть использованы вместо распаковки кортежа выше.grouper- значение атрибута, аlist- элементы с этим значением.<ul>{% for group in users|groupby("city") %} <li>{{ group.grouper }}: {{ group.list|join(", ") }} {% endfor %}</ul>Изменения
Изменено в версии 2.6: Атрибут поддерживает нотацию точек для вложенного доступа.
-
indent(s, width=4, first=False, blank=False, indentfirst=None) -
Возвращает копию строки с отступом каждой строки на 4 пробела. Первая строка и пустые строки по умолчанию не отступом.
- Параметры
-
- width – Количество пробелов для отступа.
- first – Не пропускать отступ первой строки.
- blank – Не пропускать отступ пустых строк.
Изменения
Изменено в версии 2.10: Пустые строки по умолчанию не отступаются.
Переименован аргумент
indentfirstнаfirst.
-
int(value, default=0, base=10) -
Преобразует значение в целое число. Если преобразование не выполняется, возвращает
0. Можно переопределить это значение по умолчанию, используя первый параметр. Также можно переопределить значение основания по умолчанию (10) во втором параметре, который обрабатывает входные данные с префиксами, такими как 0b, 0o и 0x для оснований 2, 8 и 16 соответственно. Основание игнорируется для десятичных чисел и значений, отличных от строк.
-
join(value, d='', attribute=None) -
Возвращает строку, которая является конкатенацией строк в последовательности. Разделитель между элементами — пустая строка по умолчанию, вы можете определить его с помощью необязательного параметра:
{{ [1, 2, 3]|join('|') }} -> 1|2|3 {{ [1, 2, 3]|join }} -> 123Также можно объединить определённые атрибуты объекта:
{{ users|join(', ', attribute='username') }}Изменения
Добавлено в версии 2.6: Добавлен параметр
attribute.
-
last(seq) -
Возвращает последний элемент последовательности.
Примечание: Не работает с генераторами. Вы можете явно преобразовать его в список:
{{ data | selectattr('name', '==', 'Jinja') | list | last }}
-
length(obj, /) -
Возвращает количество элементов в контейнере.
- Псевдонимы
-
count
-
list(value) -
Преобразует значение в список. Если это была строка, возвращаемый список будет списком символов.
-
lower(s) -
Преобразует значение в нижний регистр.
-
map(*args, **kwargs) -
Применяет фильтр к последовательности объектов или ищет атрибут. Это полезно при работе со списками объектов, но вас интересует только определенное значение.
Базовое использование — отображение атрибута. Представьте, что у вас есть список пользователей, но вас интересует только список имен пользователей:
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) (u.username or "Anonymous" for u in users) (do_lower(x) for x in titles)
Изменено в версии 2.11.0: Добавлен параметр
default.Изменения
Добавлено в версии 2.7.
-
max(value, case_sensitive=False, attribute=None) -
Возвращает наибольший элемент из последовательности.
{{ [1, 2, 3]|max }} -> 3- Параметры
-
- case_sensitive – Строки в верхнем и нижнем регистре рассматриваются как разные.
- attribute – Получить объект с максимальным значением этого атрибута.
-
min(value, case_sensitive=False, attribute=None) -
Возвращает наименьший элемент из последовательности.
{{ [1, 2, 3]|min }} -> 1- Параметры
-
- case_sensitive – Строки в верхнем и нижнем регистре рассматриваются как разные.
- attribute – Получить объект с минимальным значением этого атрибута.
-
pprint(value, verbose=False) -
Красивая печать переменной. Полезно для отладки.
Начиная с Jinja 1.2, можно передать параметр. Если этот параметр имеет истинное значение, вывод будет более подробным (требуется
pretty).
-
random(seq) -
Возвращает случайный элемент из последовательности.
-
reject(*args, **kwargs) -
Фильтрует последовательность объектов, применяя тест к каждому объекту и отклоняя объекты, для которых тест выполняется успешно.
Если тест не указан, каждый объект оценивается как булево значение.
Пример использования:
{{ numbers|reject("odd") }}Аналогично генераторному пониманию, такому как:
(n for n in numbers if not test_odd(n))
Изменения
Добавлено в версии 2.7.
-
rejectattr(*args, **kwargs) -
Фильтрует последовательность объектов, применяя тест к указанному атрибуту каждого объекта и отклоняя объекты, для которых тест выполняется успешно.
Если тест не указан, значение атрибута оценивается как булево значение.
{{ 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.
-
replace(s, old, new, count=None) -
Возвращает копию значения со всеми вхождениями подстроки, заменённой новой. Первый аргумент — подстрока, которая должна быть заменена, второй — строка замены. Если указан необязательный третий аргумент
count, заменяются только первыеcountвхождения:{{ "Hello World"|replace("Hello", "Goodbye") }} -> Goodbye World {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} -> d'oh, d'oh, aaargh
-
reverse(value) -
Инвертирует объект или возвращает итератор, который перебирает его в обратном порядке.
-
round(value, precision=0, method='common') -
Округляет число до заданной точности. Первый параметр указывает точность (по умолчанию
0), второй — метод округления:-
'common'округляет вверх или вниз -
'ceil'всегда округляет вверх -
'floor'всегда округляет вниз
Если метод не указан, используется
'common'.{{ 42.55|round }} -> 43.0 {{ 42.55|round(1, 'floor') }} -> 42.5Обратите внимание, что даже при округлении до 0 точности возвращается число с плавающей точкой. Если вам нужно целое число, пропустите его через
int:{{ 42.55|round|int }} -> 43 -
-
safe(value) -
Помечает значение как безопасное, что означает, что в среде с включённой автоматической экранировкой эта переменная не будет экранироваться.
-
select(*args, **kwargs) -
Фильтрует последовательность объектов, применяя тест к каждому объекту и выбирая только объекты, для которых тест выполняется успешно.
Если тест не указан, каждый объект оценивается как булево значение.
Пример использования:
{{ 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))
Изменения
Добавлено в версии 2.7.
-
selectattr(*args, **kwargs) -
Фильтрует последовательность объектов, применяя тест к указанному атрибуту каждого объекта и выбирая только объекты, для которых тест выполняется успешно.
Если тест не указан, значение атрибута оценивается как булево значение.
Пример использования:
{{ 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))
Изменения
Добавлено в версии 2.7.
-
slice(value, slices, fill_with=None) -
Разбивает итератор и возвращает список списков, содержащих эти элементы. Полезно, если вы хотите создать 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>Если вы передаёте второй аргумент, он используется для заполнения отсутствующих значений на последней итерации.
-
sort(value, reverse=False, case_sensitive=False, attribute=None) -
Сортирует итерируемый объект, используя функцию Python
sorted().{% for city in cities|sort %} ... {% endfor %}- Параметры
-
- reverse – Сортировать в обратном порядке.
- case_sensitive – При сортировке строк сортировать верхний и нижний регистр раздельно.
-
attribute – При сортировке объектов или словарей сортировать по атрибуту или ключу. Может использовать точечную нотацию, например
"address.city". Может быть списком атрибутов, например"age,name".
Сортировка стабильная, она не меняет относительный порядок элементов, которые сравниваются как равные. Это позволяет объединять сортировки по разным атрибутам и упорядочиваниям.
{% for user in users|sort(attribute="name") |sort(reverse=true, attribute="age") %} ... {% endfor %}В качестве сокращения при объединении, когда направление одинаковое для всех атрибутов, передайте запятой разделённый список атрибутов.
{% for user users|sort(attribute="age,name") %} ... {% endfor %}Изменено в версии 2.11.0: Параметр
attributeможет быть запятой разделённым списком атрибутов, например"age,name".Изменения
Изменено в версии 2.6: Добавлен параметр
attribute.
-
string(object) -
Преобразует строку в unicode, если она таковой не является. Таким образом, строка разметки не преобразуется обратно в unicode.
-
Удаляет теги SGML/XML и заменяет смежные пробелы одним пробелом.
-
sum(iterable, attribute=None, start=0) -
Возвращает сумму последовательности чисел плюс значение параметра ‘start’ (по умолчанию 0). Если последовательность пустая, возвращает start.
Также возможно суммировать только определённые атрибуты:
Total: {{ items|sum(attribute='price') }}Changelog
Изменено в версии 2.6: Параметр
attributeбыл добавлен для суммирования по атрибутам. Также параметрstartбыл перемещен вправо.
-
title(s) -
Возвращает заглавную версию значения. То есть слова будут начинаться с заглавных букв, все остальные символы — строчные.
-
tojson(value, indent=None) -
Преобразует структуру в JSON для безопасного использования в тегах
<script>. Принимает те же аргументы и возвращает строку JSON. Обратите внимание, что это доступно в шаблонах через фильтр|tojson, который также помечает результат как безопасный. Из-за того, как эта функция экранирует определенные символы, она безопасна даже если используется вне тегов<script>.В строках экранируются следующие символы:
<>&'
Это делает такие строки безопасными для встраивания в любое место HTML, за исключением атрибутов в двойных кавычках. В этом случае используйте атрибуты в одинарных кавычках или выполните HTML-экранирование дополнительно.
Параметр indent можно использовать для включения красивой печати. Установите его в количество пробелов, с которыми должны быть отступы структур.
Обратите внимание, что этот фильтр предназначен только для использования в контексте HTML.
Changelog
Новое в версии 2.9.
-
trim(value, chars=None) -
Удаляет начальные и конечные символы, по умолчанию пробелы.
-
truncate(s, length=255, killwords=False, end='...', leeway=None) -
Возвращает усеченную копию строки. Длина задаётся первым параметром, который по умолчанию равен
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, но его можно настроить глобально.
-
unique(value, case_sensitive=False, attribute=None) -
Возвращает список уникальных элементов из заданного итерируемого объекта.
{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} -> ['foo', 'bar', 'foobar']Уникальные элементы выдаются в том же порядке, что и их первое появление в итерируемом объекте, переданном фильтру.
- Параметры
-
- case_sensitive – Рассматривать строчные и заглавные буквы как различные.
- attribute – Фильтровать объекты с уникальными значениями для этого атрибута.
-
upper(s) -
Преобразовать значение в верхний регистр.
-
urlencode(value) -
Кодировать данные для использования в пути или запросе URL с использованием UTF-8.
Базовая обертка вокруг
urllib.parse.quote()при передаче строки илиurllib.parse.urlencode()для словаря или итерируемого объекта.- Параметры
-
value – Данные для кодирования. Строка будет закодирована напрямую. Словарь или итерируемый объект пар
(key, value)будет объединён в строку запроса.
При передаче строки символ «/» не кодируется. Веб-серверы обрабатывают «/» и «%2F» в путях эквивалентно. Если вам нужно закодировать слэши, используйте фильтр
|replace("/", "%2F").Changelog
Новое в версии 2.7.
-
urlize(value, trim_url_limit=None, nofollow=False, target=None, rel=None) -
Преобразует URL в обычном тексте в нажимаемые ссылки.
Если вы передаёте фильтру дополнительное целое число, он сократит URL до этого числа. Также существует третий аргумент, который делает URL «nofollow»:
{{ mytext|urlize(40, true) }} links are shortened to 40 chars and defined with rel="nofollow"Если указан target, атрибут
targetбудет добавлен к тегу<a>:{{ mytext|urlize(40, target='_blank') }}Changelog
Изменено в версии 2.8+: Добавлен параметр target.
-
wordcount(s) -
Подсчёт слов в строке.
-
wordwrap(s, width=79, break_long_words=True, wrapstring=None, break_on_hyphens=True) -
Перенос строки по заданной ширине. Существующие новые строки рассматриваются как абзацы, которые следует переносить отдельно.
- Параметры
-
- s – Исходный текст для переноса.
- width – Максимальная длина переноса строк.
-
break_long_words – Если слово длиннее
width, разбивать его на строки. - break_on_hyphens – Если слово содержит дефисы, его можно разбить на строки.
-
wrapstring – Строка для объединения каждой строки переноса. По умолчанию
Environment.newline_sequence.
Изменено в версии 2.11: Существующие новые строки рассматриваются как абзацы, которые переносятся отдельно.
Изменено в версии 2.11: Добавлен параметр
break_on_hyphens.Changelog
Изменено в версии 2.7: Добавлен параметр
wrapstring.
-
xmlattr(d, autospace=True) -
Создать строку атрибутов 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.
Список встроенных тестов
-
boolean(value) -
Возвращает true, если объект является булевым значением.
Новое в версии 2.11.
-
callable(obj, /) -
Возвращает, является ли объект вызываемым (то есть каким-либо видом функции).
Обратите внимание, что классы вызываемы, как и экземпляры классов с методом __call__().
-
defined(value) -
Возвращает true, если переменная определена:
{% if variable is defined %} value of variable: {{ variable }} {% else %} variable is not defined {% endif %}См. фильтр
default()для простого способа установки неопределённых переменных.
-
divisibleby(value, num) -
Проверяет, делится ли переменная на число.
-
eq(a, b, /) -
То же самое, что и a == b.
- Псевдонимы
-
==,equalto
-
escaped(value) -
Проверить, является ли значение экранированным.
-
even(value) -
Возвращает true, если переменная чётная.
-
false(value) -
Возвращает true, если объект равен False.
Новое в версии 2.11.
-
float(value) -
Возвращает true, если объект является числом с плавающей точкой.
Новое в версии 2.11.
-
ge(a, b, /) -
То же самое, что и a >= b.
- Псевдонимы
-
>=
-
gt(a, b, /) -
То же самое, что и a > b.
- Псевдонимы
-
>,greaterthan
-
in(value, seq) -
Проверить, находится ли значение в seq.
Changelog
Новое в версии 2.10.
-
integer(value) -
Возвращает true, если объект является целым числом.
Новое в версии 2.11.
-
iterable(value) -
Проверить, можно ли итерировать по объекту.
-
le(a, b, /) -
То же самое, что и a <= b.
- Псевдонимы
-
<=
-
lower(value) -
Возвращает true, если переменная приведена к нижнему регистру.
-
lt(a, b, /) -
То же самое, что и a < b.
- Псевдонимы
-
<,lessthan
-
mapping(value) -
Возвращает true, если объект является отображением (словарь и т.д.).
Changelog
Новое в версии 2.6.
-
ne(a, b, /) -
То же самое, что и a != b.
- Псевдонимы
-
!=
-
none(value) -
Возвращает true, если переменная равна None.
-
number(value) -
Возвращает true, если переменная является числом.
-
odd(value) -
Возвращает true, если переменная нечётная.
-
sameas(value, other) -
Проверить, ссылается ли объект на тот же адрес памяти, что и другой объект:
{% if foo.attribute is sameas false %} the foo attribute really is the `False` singleton {% endif %}
-
sequence(value) -
Возвращает true, если переменная является последовательностью. Последовательности — это переменные, по которым можно итерироваться.
-
string(value) -
Возвращает true, если объект является строкой.
-
true(value) -
Возвращает true, если объект равен True.
Новое в версии 2.11.
-
undefined(value) -
Аналогично
defined(), но наоборот.
-
upper(value) -
Возвращает true, если переменная приведена к верхнему регистру.
Список глобальных функций
По умолчанию доступны следующие функции в глобальной области:
-
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>
-
lipsum(n=5, html=True, min=20, max=100) -
Генерирует lorem ipsum для шаблона. По умолчанию генерируются пять абзацев HTML, при этом каждый абзац содержит от 20 до 100 слов. Если html равен False, возвращается обычный текст. Это полезно для генерации простого контента для тестирования макета.
-
dict(**items) -
Удобная альтернатива литералам словарей.
{'foo': 'bar'}эквивалентноdict(foo='bar').
-
class cycler(*items) -
Cycler позволяет циклически перебирать значения, подобно тому, как работает
loop.cycle. В отличие отloop.cycle, этим циклом можно пользоваться вне циклов или во множестве циклов.Это может быть очень полезно, если вы хотите показать список папок и файлов, располагая папки сверху, но оба в одном списке с чередующимися цветами строк.
Следующий пример демонстрирует, как можно использовать
cycler:{% set row_class = cycler('odd', 'even') %} <ul class="browser"> {% for folder in folders %} <li class="folder {{ row_class.next() }}">{{ folder|e }}</li> {% endfor %} {% for filename in files %} <li class="file {{ row_class.next() }}">{{ filename|e }}</li> {% endfor %} </ul>У цикла есть следующие атрибуты и методы:
-
reset() -
Сбрасывает цикл до первого элемента.
-
next() -
Переходит к следующему элементу и возвращает текущий элемент.
-
current -
Возвращает текущий элемент.
Changelog
Новое в версии 2.1.
-
-
class joiner(sep=', ') -
Небольшой вспомогательный инструмент, который можно использовать для «соединения» нескольких разделов. Joiner получает строку и возвращает эту строку каждый раз, когда его вызывают, за исключением первого раза (в этом случае он возвращает пустую строку). Это можно использовать для соединения вещей:
{% 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 %}Changelog
Новое в версии 2.1.
-
class 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 }}Changelog
Новое в версии 2.10.
Расширения
В следующих разделах описаны встроенные расширения Jinja2, которые могут быть включены приложением. Приложение также может предоставить дополнительные расширения, не охваченные этой документацией; в этом случае должна быть отдельная документация, описывающая данные расширения.
Международная поддержка
Если расширение i18n включено, то можно пометить части шаблона как переводимые. Для обозначения переводимого раздела можно использовать trans:
<p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
Для перевода выражения шаблона — скажем, с использованием фильтров шаблонов или просто путем доступа к атрибуту объекта — нужно привязать выражение к имени для использования в блоке перевода:
<p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
Если вам нужно привязать более одного выражения внутри тега trans , разделяйте части запятой (,):
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}
Внутри тегов trans разрешены только теги переменных, а не операторы.
Для множественного числа укажите оба единственное и множественное числа с помощью тега pluralize , который находится между trans и endtrans:
{% 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 можно пометить как обрезной (trimmed), что заменит все переводы строк и пробелы вокруг них одним пробелом и удалит ведущие/завершающие пробелы:
{% trans trimmed book_title=book.title %}
This is {{ book_title }}.
You should read it!
{% endtrans %}
Если обрезка включена глобально, модификатор notrimmed можно использовать для отключения её для блока trans.
Changelog
Новое в версии 2.10: Добавлены модификаторы trimmed и notrimmed.
Также можно переводить строки в выражениях. Для этого существуют три функции:
-
gettext: перевести одну строку -
ngettext: перевести строку, допускающую множественное число -
_: псевдоним дляgettext
Например, вы можете легко вывести переведённую строку так:
{{ _('Hello World!') }}
Для использования заполнительных элементов используйте фильтр format:
{{ _('Hello %(user)s!')|format(user=user.username) }}
Для нескольких заполнительных элементов всегда используйте ключевые аргументы для format, так как другие языки могут не использовать слова в том же порядке.
Changelog
Изменено в версии 2.5.
Если вызываются функции gettext нового стиля (Удаление пробелов), использование заготовок намного проще:
{{ 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 (См.: Для).
Оператор 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. Это создавало проблемы с поведением очищенной области видимости и с тех пор было улучшено. В частности, в более новых версиях Jinja2 следующий код всегда ссылается на переменную a извне блока with.
{% with a={}, b=a.attribute %}...{% endwith %}
В более ранних версиях Jinja атрибут b ссылался на результаты первого атрибута. Если вы полагаетесь на это поведение, вы можете переписать его, используя тэг set:
{% with a={} %}
{% set b = a.attribute %}
{% endwith %}
Расширение
В более ранних версиях Jinja (до 2.9) для активации этой функции требовалось расширение. Теперь она включена по умолчанию.
Переопределения Autoescape
Журнал изменений
В версии 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–2020 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/2.10.x/templates/