Документация шаблонизатора
Данный документ описывает синтаксис и семантику движка шаблонов и будет наиболее полезен в качестве справочника для тех, кто создаёт шаблоны 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.
Примечание
Вы не должны добавлять пробелы между тегом и знаком минус.
действительно:
{%- 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», добавив модификатор 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.
Работа с ручным экранированием
Если ручное экранирование включено, вы необходимость экранировать переменные, если это необходимо. Что экранировать? Если у вас есть переменная, которая может содержать любой из следующих символов (>, <, &, или "), вы ДОЛЖНЫ экранировать её, если переменная не содержит правильно сформированного и надёжного HTML. Экранирование выполняется путём передачи переменной через фильтр |e.
{{ user.username|e }}
Работа с автоматическим экранированием
Когда автоматическое экранирование включено, всё экранируется по умолчанию, за исключением значений, явно помеченных как безопасные. Переменные и выражения могут быть помечены как безопасные либо в:
- словаре контекста приложением с помощью
MarkupSafe.Markup, или - в шаблоне, с помощью фильтра
|safe
Основная проблема этого подхода в том, что сам Python не имеет понятия о заражённых значениях; поэтому информация о том, является ли значение безопасным или небезопасным, может быть потеряна.
Если значение не помечено как безопасное, произойдёт автоматическое экранирование; это означает, что у вас может получиться двойное экранирование содержимого. Однако избежать двойного экранирования легко: просто используйте инструменты, предоставляемые Jinja2, и не используйте встроенные конструкции Python, такие как str.format или оператор модуля строки (%).
Функции Jinja2 (макросы, super, self.BLOCKNAME) всегда возвращают данные шаблона, помеченные как безопасные.
Строковые литералы в шаблонах с автоматическим экранированием считаются небезопасными, потому что обычные строки Python (str, unicode, basestring) не являются безопасными строками с атрибутом MarkupSafe.Markup.
Список управляющих структур
Управляющая структура относится ко всем элементам, которые управляют потоком программы — условные операторы (т. е. 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.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
Однако обратите внимание, что списки Python не упорядочены; поэтому вы можете либо передать отсортированный list списков tuple, или collections.OrderedDict, в шаблон, либо использовать фильтр dictsort.
Внутри блока цикла for вы можете получить доступ к некоторым специальным переменным:
Переменная | Описание |
|---|---|
| Текущее значение итерации цикла. (Индексирование с 1). |
| Текущее значение итерации цикла. (Индексирование с 0). |
| Номер итерации с конца цикла (индексирование с 1). |
| Номер итерации с конца цикла (индексирование с 0). |
| True, если это первая итерация. |
| True, если это последняя итерация. |
| Количество элементов в последовательности. |
| Функция-помощник для циклической переборки списка последовательностей. См. объяснение ниже. |
| Указывает глубину вложенности циклов при текущем рендеринге. Начинается с уровня 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 была ошибка, при которой в некоторых обстоятельствах присваивания, казалось, работали. Это не поддерживается. См. Присваивания для получения дополнительной информации о том, как с этим справиться.
Условный оператор
Оператор if в Jinja сравним с оператором if в Python. В простейшей форме вы можете использовать его для проверки, определена ли переменная, не пуста и не равна false:
{% 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 -
Если макрос был вызван из тега вызова, вызывающий элемент хранится в этой переменной как вызываемый макрос.
Макросы также предоставляют доступ к некоторым внутренним деталям. Следующие атрибуты доступны для объекта макроса:
-
name -
Имя макроса.
{{ input.name }}будет выводитьinput. -
arguments -
Кортеж имён аргументов, которые принимает макрос.
-
defaults -
Кортеж значений по умолчанию.
-
catch_kwargs -
Это
true, если макрос принимает дополнительные именованные аргументы (т.е.: обращается к специальной переменнойkwargs). -
catch_varargs -
Это
true, если макрос принимает дополнительные позиционные аргументы (т.е.: обращается к специальной переменнойvarargs). -
caller -
Это
true, если макрос обращается к специальной переменнойcallerи может быть вызван из тега вызова.
Если имя макроса начинается с подчёркивания, оно не экспортируется и не может быть импортировано.
Вызов
В некоторых случаях может быть полезно передать макрос другому макросу. Для этого можно использовать специальный блок 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.8.
Начиная с Jinja 2.8, можно также использовать блочные присваивания для захвата содержимого блока в имя переменной. Это может быть полезно в некоторых ситуациях как альтернатива макросам. В этом случае вместо использования знака равенства и значения вы просто пишете имя переменной, а затем всё до {% endset %} будет захвачено.
Пример:
{% set navigation %}
<li><a href="/">Index</a>
<li><a href="/downloads">Downloads</a>
{% endset %}
Переменная navigation затем содержит исходный HTML-код навигации.
Расширение
Тег 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 %}
Изменения
Введено в версии 2.2.
Также можно предоставить список шаблонов, проверяемых на существование перед включением. Первый существующий шаблон будет включён. Если ignore missing задано, он вернётся к рендерингу ничего, если ни один из шаблонов не существует, иначе он поднимет исключение.
Пример:
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}
Изменения
Изменено в версии 2.4: Если объект шаблона был передан в контекст шаблона, можно включить этот объект с помощью include.
Импорт
Jinja2 поддерживает размещение часто используемого кода в макросы. Эти макросы могут быть помещены в разные шаблоны и импортированы из них. Это работает аналогично операторам импорта в 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 к директиве импорта/включения, текущий контекст может быть передан шаблону, а кэширование автоматически отключено.
Вот два примера:
{% 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 }}. (Точно так же, какfrom __future__ import division.)
- //
-
Делит два числа и возвращает усечённый целочисленный результат.
{{ 20 // 7 }}это2.
- %
-
Вычисляет остаток от целочисленного деления.
{{ 11 % 7 }}это4. - *
-
Умножает левый операнд на правый.
{{ 2 * 2 }}вернёт4. Это также можно использовать для многократного повторения строки.{{ '=' * 80 }}напечатает полосу из 80 равных знаков. - **
-
Возводит левый операнд в степень правого.
{{ 2**3 }}вернёт8.
Сравнения
- ==
-
Сравнивает два объекта на равенство.
- !=
-
Сравнивает два объекта на неравенство.
- >
-
trueесли левая часть больше правой. - >=
-
trueесли левая часть больше или равна правой.
- <
-
trueесли левая часть меньше правой. - <=
-
trueесли левая часть меньше или равна правой.
Логика
Для if заявлений, фильтрации for и выражений if может быть полезно комбинировать несколько выражений:
- and
-
Возвращает true, если левый и правый операнды истинны.
- or
-
Возвращает 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 }}
Список встроенных фильтров
-
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, используются двоичные префиксы (Мeби, Гиби).
-
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’s
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’s
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) -
Проверка, содержится ли значение в последовательности.
Журнал изменений
Новая версия 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, если объект является отображением (словарь и т. д.).
Журнал изменений
Новая версия 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. Когда задан шаг, он определяет приращение (или убывание). Например,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>У cycler есть следующие атрибуты и методы:
-
reset() -
Сбрасывает цикл до первого элемента.
-
next() -
Переходит к следующему элементу и возвращает текущий элемент.
-
current -
Возвращает текущий элемент.
Новое в Jinja 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 %}Новое в Jinja 2.1
Расширения
В следующих разделах рассматриваются встроенные расширения Jinja2, которые могут быть включены приложением. Приложение также может предоставлять дополнительные расширения, не охваченные этим документом; в этом случае должен быть отдельный документ, объясняющий указанные расширения.
i18n в шаблонах
Если расширение 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 %}
Также можно переводить строки в выражениях. Для этой цели существуют три функции:
-
gettext: перевод одной строки -
ngettext: перевод переводимой строки -
_: псевдоним дляgettext
Например, можно легко вывести переведённую строку так:
{{ _('Hello World!') }}
Для использования заменителей используйте фильтр format:
{{ _('Hello %(user)s!')|format(user=user.username) }}
Для нескольких заменителей всегда используйте именованные аргументы для format, так как другие языки могут использовать слова не в том же порядке.
Журнал изменений
Изменено в версии 2.5.
Если включены вызовы gettext нового стиля (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 (См.: Цикл for).
Оператор with
Изменения
В версии 2.3.
Оператор with позволяет создать новую внутреннюю область видимости. Переменные, заданные в этой области, не видны за её пределами.
Смысл with вкратце:
{% with %}
{% set foo = 42 %}
{{ foo }} foo is 42 here
{% endwith %}
foo is not visible here any longer
Поскольку часто переменные задаются в начале области видимости, вы можете сделать это внутри оператора with. Два следующих примера эквивалентны:
with Важное замечание по области видимости. В версиях 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) для включения этой функции требовалось расширение. Сейчас она включена по умолчанию.
Переопределения автоэскейпа
Изменения
В версии 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.9.x/templates/