Документация по шаблонизатору
В данном документе описывается синтаксис и семантика движка шаблонов, и он будет наиболее полезен в качестве справочника для тех, кто создаёт шаблоны Jinja. Поскольку движок шаблонов очень гибкий, конфигурация из приложения может незначительно отличаться от представленного здесь кода с точки зрения разделителей и поведения неопределённых значений.
Обзор
Шаблон Jinja — это просто текстовый файл. Jinja может генерировать любой текстовый формат (HTML, XML, CSV, LaTeX и т. д.). Шаблону Jinja не нужно иметь определённое расширение: .html, .xml или любое другое расширение подойдёт.
Шаблон содержит переменные и/или выражения, которые заменяются значениями при рендеринге шаблона; и теги, которые управляют логикой шаблона. Синтаксис шаблона сильно вдохновлён Django и Python.
Ниже приведен минимальный шаблон, который иллюстрирует несколько основных моментов, используя стандартную конфигурацию Jinja. Мы рассмотрим детали позже в этом документе:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
{# a comment #}
</body>
</html>
В следующем примере показаны настройки по умолчанию. Разработчик приложения может изменить конфигурацию синтаксиса от {% foo %} до <% foo
%> или что-то подобное.
Существует несколько типов разделителей. Разделители Jinja по умолчанию настроены следующим образом:
-
{% ... %}для Операторов -
{{ ... }}для Выражений для вывода в выходные данные шаблона -
{# ... #}для Комментарии, не включаемых в выходные данные шаблона
Операторы и комментарии в строках также возможны, хотя у них нет префиксных символов по умолчанию. Чтобы использовать их, установите line_statement_prefix и line_comment_prefix при создании Environment.
Расширение файла шаблона
Как указано выше, любой файл может загружаться как шаблон, независимо от расширения файла. Добавление .jinja расширения, например user.html.jinja, может упростить работу некоторых IDE или плагинов редактора, но не является обязательным. Автоматическое экранирование, введённое позже, может применяться на основе расширения файла, поэтому вам нужно учитывать дополнительный суффикс в этом случае.
Другим хорошим эвристическим правилом для идентификации шаблонов является то, что они находятся в папке templates, независимо от расширения. Это распространённая структура проекта.
Переменные
Переменные шаблона определяются словарем контекста, передаваемым шаблону.
Вы можете работать с переменными в шаблонах, при условии, что они переданы приложением. Переменные могут иметь атрибуты или элементы, которые вы можете получить. Какие атрибуты есть у переменной, сильно зависит от приложения, предоставляющего эту переменную.
Вы можете использовать точку (.) для доступа к атрибутам переменной, помимо стандартного синтаксиса Python __getitem__ «подстроки» ([]).
Следующие строки делают одно и то же:
{{ foo.bar }}
{{ foo['bar'] }}
Важно знать, что внешние двойные фигурные скобки не являются частью переменной, а оператором вывода. Если вы обращаетесь к переменным внутри тегов, не ставьте фигурные скобки вокруг них.
Если переменная или атрибут не существует, вы получите неопределённое значение. Что вы можете сделать с таким значением, зависит от конфигурации приложения: по умолчанию оно вычисляется как пустая строка при выводе или итерировании и возвращает ошибку для других операций.
Реализация
Для удобства, foo.bar в Jinja выполняет следующие действия на уровне Python:
- проверка наличия атрибута, названного
bar, уfoo(getattr(foo, 'bar')) - если его нет, проверка наличия элемента
'bar'вfoo(foo.__getitem__('bar')) - если его нет, возвращает неопределённый объект.
foo['bar'] работает в основном также с небольшим изменением последовательности:
- проверка наличия элемента
'bar'вfoo. (foo.__getitem__('bar')) - если его нет, проверка наличия атрибута, названного
bar, уfoo. (getattr(foo, 'bar')) - если его нет, возвращает неопределённый объект.
Это важно, если у объекта есть элемент и атрибут с одинаковым именем. Кроме того, фильтр attr() ищет только атрибуты.
Фильтры
Переменные могут быть изменены фильтрами. Фильтры отделяются от переменной символом «|» (|) и могут иметь необязательные аргументы в скобках. Можно использовать несколько фильтров. Результат одного фильтра применяется к следующему.
Например, {{ name|striptags|title }} удалит все HTML-теги из переменной name и приведёт результат к верхнему регистру (title(striptags(name))).
Фильтры, принимающие аргументы, имеют скобки вокруг аргументов, как при вызове функции. Например, {{ listx|join(', ') }} объединит список запятыми (str.join(', ', listx)).
В разделе Список встроенных фильтров ниже описаны все встроенные фильтры.
Тесты
Помимо фильтров, также доступны так называемые «тесты». Тесты могут использоваться для проверки переменной на соответствие общему выражению. Чтобы проверить переменную или выражение, добавьте is и имя теста после переменной. Например, чтобы проверить, определена ли переменная, можно выполнить name is defined, что затем вернёт true или false в зависимости от того, определена ли name в текущем контексте шаблона.
Тесты также могут принимать аргументы. Если тест принимает только один аргумент, можно опустить скобки. Например, следующие два выражения выполняют одно и то же:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
В разделе Список встроенных тестов ниже описаны все встроенные тесты.
Управление пробелами
В конфигурации по умолчанию:
- одна единственная конечная перенос строки удаляется, если она присутствует
- другие пробелы (пробелы, табуляции, переносы строк и т. д.) возвращаются без изменений
Если приложение настраивает Jinja на trim_blocks, первая перенос строки после тега шаблона автоматически удаляется (как в PHP). Опция lstrip_blocks также может быть установлена для удаления табуляций и пробелов с начала строки до начала блока. (Ничего не будет удалено, если перед началом блока есть другие символы.)
При включении как trim_blocks, так и lstrip_blocks, вы можете размещать теги блоков на отдельных строках, и вся строка блока будет удалена при рендеринге, сохраняя пробелы содержимого. Например, без опций trim_blocks и lstrip_blocks этот шаблон:
<div>
{% if True %}
yay
{% endif %}
</div>
отображается с пустыми строками внутри div:
<div>
yay
</div>
Но с включенными trim_blocks и lstrip_blocks строки блоков шаблона удаляются, а другие пробелы сохраняются:
<div>
yay
</div>
Вы можете вручную отключить поведение lstrip_blocks, поместив знак плюс (+) в начале блока:
<div>
{%+ if something %}yay{% endif %}
</div>
Аналогично, вы можете вручную отключить поведение trim_blocks, поместив знак плюс (+) в конце блока:
<div>
{% if something +%}
yay
{% endif %}
</div>
Вы также можете удалить пробелы в шаблонах вручную. Если вы добавите знак минус (-) в начало или конец блока (например, тега Для), комментария или выражения переменной, пробелы перед или после этого блока будут удалены:
{% for item in seq -%}
{{ item }}
{%- endfor %}
Это даст все элементы без пробелов между ними. Если seq был списком чисел от 1 до 9, выходными данными были бы 123456789.
Если Операторы в строках включены, они автоматически удаляют ведущие пробелы до начала строки.
По умолчанию Jinja также удаляет конечные переносы строк. Чтобы сохранить одиночные конечные переносы строк, настройте Jinja на keep_trailing_newline.
Примечание
Не следует добавлять пробелы между тегом и знаком минус.
Допустимо:
{%- if foo -%}...{% endif %}
Недопустимо:
{% - if foo - %}...{% endif %}
Экранирование
Иногда желательно — даже необходимо — заставить Jinja игнорировать части, которые он в противном случае обрабатывает как переменные или блоки. Например, если с помощью стандартного синтаксиса вы хотите использовать {{ как необработанную строку в шаблоне и не начинать переменную, нужно использовать трюк.
Самый простой способ вывести литеральный разделитель переменной ({{) — использовать выражение переменной:
{{ '{{' }}
Для больших блоков имеет смысл пометить блок raw. Например, чтобы включить пример синтаксиса Jinja в шаблон, можно использовать этот фрагмент:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
Примечание
Знак минус в конце тега {% raw -%} очищает все пробелы и переносы строк, предшествующие первому символу ваших необработанных данных.
Утверждения строк
Если утверждения строк включены приложением, можно пометить строку как утверждение. Например, если префикс утверждения строки настроен на #, следующие два примера эквивалентны:
<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
Префикс утверждения строки может появиться где угодно в строке, при условии, что перед ним нет текста. Для лучшей читаемости утверждения, которые начинают блок (например, for, if, elif и т.д.) могут заканчиваться двоеточием:
# for item in seq:
...
# endfor
Примечание
Утверждения строк могут занимать несколько строк, если есть открытые скобки, фигурные скобки или квадратные скобки:
<ul>
# for href, caption in [('index.html', 'Index'),
('about.html', 'About')]:
<li><a href="{{ href }}">{{ caption }}</a></li>
# endfor
</ul>
С Jinja 2.2 также доступны комментарии на основе строк. Например, если префикс комментария к строке настроен на ##, всё от ## до конца строки игнорируется (кроме знака новой строки):
# for item in seq:
<li>{{ item }}</li> ## this comment is ignored
# endfor
Наследование шаблонов
Самая мощная часть Jinja — это наследование шаблонов. Наследование шаблонов позволяет создать базовый «каркас» шаблона, содержащий все общие элементы вашего сайта и определять блоки, которые дочерние шаблоны могут переопределять.
Звучит сложно, но очень просто. Лучше всего понять это, начав с примера.
Базовый шаблон
Этот шаблон, который мы назовем base.html, определяет простой HTML-каркас документа, который вы можете использовать для простой страницы с двумя колонками. Задача «дочерних» шаблонов — заполнить пустые блоки содержимым:
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
В этом примере теги {% block %} определяют четыре блока, которые могут заполнить дочерние шаблоны. Всё, что делает тег block, — это сообщает движку шаблонов, что дочерний шаблон может переопределить эти места в шаблоне.
Теги block могут находиться внутри других блоков, таких как if, но они всегда будут выполняться независимо от того, будет ли блок if фактически отображаться.
Дочерний шаблон
Дочерний шаблон может выглядеть так:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
Тег {% extends %} является ключевым. Он сообщает движку шаблонов, что этот шаблон «расширяет» другой шаблон. Когда система шаблонов оценивает этот шаблон, она сначала находит родительский. Тег extends должен быть первым тегом в шаблоне. Всё, что перед ним, выводится обычно и может вызвать путаницу. Подробности об этом поведении и о том, как извлечь из этого выгоду, см. в Null-Default Fallback. Также блок всегда будет заполнен независимо от того, будет ли окружающее условие оценено как истинное или ложное.
Имя файла шаблона зависит от загрузчика шаблонов. Например, FileSystemLoader позволяет получить доступ к другим шаблонам, указав имя файла. Вы можете получить доступ к шаблонам в подкаталогах с помощью косой черты:
{% extends "layout/default.html" %}
Однако это поведение может зависеть от приложения, внедряющего Jinja. Обратите внимание, что поскольку дочерний шаблон не определяет блок footer, используется значение из родительского шаблона.
Вы не можете определить несколько тегов {% block %} с одинаковым именем в одном шаблоне. Это ограничение существует, потому что тег блока работает «в обоих» направлениях. То есть, тег блока не только предоставляет местозаполнитель для заполнения — он также определяет содержимое, которое заполняет местозаполнитель в родительском шаблоне. Если в шаблоне были бы два тега {% block %} с одинаковым названием, родительский шаблон не знал бы, какое содержимое блока использовать.
Однако, если вы хотите отобразить блок несколько раз, вы можете использовать специальную переменную self и вызвать блок с этим именем:
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
Блоки супер
Можно отобразить содержимое родительского блока, вызвав super(). Это возвращает результаты родительского блока:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
Вложенные расширения
В случае нескольких уровней {% extends %}, ссылки super могут быть объединены (как в super.super()), чтобы пропустить уровни в дереве наследования.
Например:
# parent.tmpl
body: {% block body %}Hi from parent.{% endblock %}
# child.tmpl
{% extends "parent.tmpl" %}
{% block body %}Hi from child. {{ super() }}{% endblock %}
# grandchild1.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild1.{% endblock %}
# grandchild2.tmpl
{% extends "child.tmpl" %}
{% block body %}Hi from grandchild2. {{ super.super() }} {% endblock %}
Отображение child.tmpl даст body: Hi from child. Hi from parent.
Отображение grandchild1.tmpl даст body: Hi from grandchild1.
Отображение grandchild2.tmpl даст body: Hi from grandchild2. Hi from parent.
Вложенность и область действия блоков
Блоки могут быть вложены для более сложных макетов. Однако по умолчанию блоки не могут получить доступ к переменным из внешних областей видимости:
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
В этом примере выведены пустые <li> элементы, потому что item недоступно внутри блока. Причина в том, что если блок заменяется дочерним шаблоном, появится переменная, которая не была определена в блоке или передана в контекст.
Начиная с Jinja 2.2, вы можете явно указать, что переменные доступны в блоке, установив блок в «области видимости», добавив модификатор scoped к объявлению блока:
{% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
{% endfor %}
При переопределении блока модификатор scoped не нужно предоставлять.
Обязательные блоки
Блоки могут быть помечены как required. Они должны быть переопределены в какой-то момент, но не обязательно непосредственно дочерним шаблоном. Обязательные блоки могут содержать только пробелы и комментарии, и их нельзя отображать напрямую.
page.txt{% block body required %}{% endblock %}
issue.txt{% extends "page.txt" %}
bug_report.txt{% extends "issue.txt" %}
{% block body %}Provide steps to demonstrate the bug.{% endblock %}
Отображение page.txt или issue.txt вызовет TemplateRuntimeError, потому что они не переопределяют блок body. Отображение bug_report.txt пройдет успешно, потому что это переопределение блока.
В сочетании с scoped модификатор required должен быть размещён после модификатора scoped. Вот несколько примеров:
{% block body scoped %}{% endblock %}
{% block body required %}{% endblock %}
{% block body scoped required %}{% endblock %}
Объекты шаблонов
Журнал изменений
Изменено в версии 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, который не понимает это обозначение, она может быть утеряна. Следите за тем, когда ваши данные помечены как безопасные и как они обрабатываются перед попаданием в шаблон.
Если значение было обработано, но не помечено как безопасное, автоматическая обработка всё равно произойдёт, что приведёт к двойной обработке символов. Если вы знаете, что у вас есть данные, которые уже безопасны, но не помечены, убедитесь, что вы обернули их в Markup или используйте фильтр |safe.
Функции Jinja (макросы, super, self.BLOCKNAME) всегда возвращают данные шаблона, помеченные как безопасные.
Строковые литералы в шаблонах с автоматической обработкой считаются небезопасными, так как собственные строки Python не являются безопасными.
Список управляющих конструкций
Управляющая конструкция относится ко всем тем элементам, которые управляют потоком программы — условные операторы (т.е. if/elif/else), циклы for, а также такие вещи, как макросы и блоки. В соответствии с исходной синтаксической конструкцией, управляющие структуры появляются внутри блоков {% ... %}.
Цикл for
Итерация по каждому элементу в последовательности. Например, для отображения списка пользователей, предоставленных в переменной под названием users:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
Поскольку переменные в шаблонах сохраняют свои свойства объекта, можно перебирать контейнеры, такие как dict:
<dl>
{% for key, value in my_dict.items() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
Python-словари могут не быть упорядочены так, как вам нужно для отображения. Если порядок имеет значение, используйте фильтр |dictsort.
<dl>
{% for key, value in my_dict | dictsort %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
</dl>
Внутри блока цикла for можно получить доступ к некоторым специальным переменным:
Переменная | Описание |
|---|---|
| Текущая итерация цикла. (индексация с 1) |
| Текущая итерация цикла. (индексация с 0) |
| Номер итерации с конца цикла (индексация с 1) |
| Номер итерации с конца цикла (индексация с 0) |
| True, если первая итерация. |
| True, если последняя итерация. |
| Количество элементов в последовательности. |
| Вспомогательная функция для циклического перебора списка последовательностей. См. объяснение ниже. |
| Указывает глубину вложенности рекурсивного цикла на текущем этапе рендеринга. Начинается с уровня 1 |
| Указывает глубину вложенности рекурсивного цикла на текущем этапе рендеринга. Начинается с уровня 0 |
| Элемент из предыдущей итерации цикла. Не определено во время первой итерации. |
| Элемент из последующей итерации цикла. Не определено во время последней итерации. |
| True, если ранее вызывался с другим значением (или вообще не вызывался). |
Внутри цикла for можно циклически перебирать список строк/переменных на каждой итерации, используя специальную вспомогательную функцию loop.cycle:
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}
Начиная с Jinja 2.1, существует дополнительная вспомогательная функция cycle, которая позволяет циклический перебор без привязки к циклу. Для получения дополнительной информации ознакомьтесь со списком глобальных функций.
В отличие от Python, в цикле нельзя break или continue. Однако вы можете отфильтровать последовательность во время итерации, что позволит пропустить элементы. Следующий пример пропускает всех скрытых пользователей:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
Преимущества в том, что специальная переменная loop будет подсчитывать правильно; таким образом, не подсчитывая пользователей, по которым не проводилась итерация.
Если итерация не произошла из-за того, что последовательность была пустой или фильтрация удалила все элементы из последовательности, можно отобразить блок по умолчанию, используя else:
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endfor %}
</ul>
Обратите внимание, что в Python блоки else выполняются всякий раз, когда соответствующий цикл не break. Поскольку циклы Jinja не могут break, был выбран несколько другой механизм работы ключевого слова else.
Также можно использовать циклы рекурсивно. Это полезно при работе с рекурсивными данными, такими как карты сайта или RDFa. Чтобы использовать рекурсивные циклы, вам нужно добавить модификатор recursive к определению цикла и вызвать переменную loop с новой итерируемой последовательностью, где вы хотите выполнить рекурсию.
Следующий пример реализует карту сайта с рекурсивными циклами:
<ul class="sitemap">
{%- for item in sitemap recursive %}
<li><a href="{{ item.href|e }}">{{ item.title }}</a>
{%- if item.children -%}
<ul class="submenu">{{ loop(item.children) }}</ul>
{%- endif %}</li>
{%- endfor %}
</ul>
Переменная loop всегда относится к ближайшему (внутреннему) циклу. Если у нас есть более одного уровня циклов, мы можем повторно связать переменную loop, написав {% set outer_loop = loop %} после цикла, который мы хотим использовать рекурсивно. Затем мы можем вызвать его, используя {{ outer_loop(…) }}
Обратите внимание, что присваивания в циклах будут очищаться в конце итерации и не могут пережить область видимости цикла. В более ранних версиях Jinja в некоторых случаях казалось, что присваивания работают. Это не поддерживается. Подробности о работе с этим см. в разделе Присваивания.
Если все, что вам нужно, — это проверить, изменилось ли какое-либо значение с момента последней итерации или изменится в следующей итерации, можно использовать previtem и nextitem:
{% for value in values %}
{% if loop.previtem is defined and value > loop.previtem %}
The value just increased!
{% endif %}
{{ value }}
{% if loop.nextitem is defined and loop.nextitem > value %}
The value will increase even more!
{% endif %}
{% endfor %}
Если вас интересует только то, изменилось ли значение вообще, использовать changed еще проще:
{% for entry in entries %}
{% if loop.changed(entry.category) %}
<h2>{{ entry.category }}</h2>
{% endif %}
<p>{{ entry.message }}</p>
{% endfor %}
Условный оператор if
Условный оператор if в Jinja сопоставим с оператором Python if. В простейшей форме можно использовать его для проверки, определена ли переменная, не пуста и не ложна:
{% if users %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
Для нескольких ветвей можно использовать elif и else, как и в Python. Там также можно использовать более сложные выражения:
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
Условный оператор if также можно использовать как встроенное выражение и для фильтрации циклов.
Макросы
Макросы аналогичны функциям в обычных языках программирования. Они полезны для размещения часто используемых выражений в повторяемых функциях, чтобы не повторяться («DRY»).
Вот небольшой пример макроса, рендеринга элемента формы:
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
Затем макрос можно вызывать как функцию в пространстве имен:
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
Если макрос был определен в другом шаблоне, его необходимо сначала импортировать.
Внутри макросов можно получить доступ к трем специальным переменным:
-
varargs -
Если в макрос передается больше позиционных аргументов, чем он принимает, они попадают в специальную переменную
varargsв виде списка значений. -
kwargs -
Как и
varargs, но для ключевых аргументов. Все неиспользованные ключевые аргументы хранятся в этой специальной переменной. -
caller -
Если макрос был вызван из тега вызова, вызывающий элемент хранится в этой переменной как вызываемый макрос.
Макросы также предоставляют доступ к некоторым внутренним деталям. На объекте макроса доступны следующие атрибуты:
-
name -
Имя макроса.
{{ input.name }}выведетinput. -
arguments -
Кортеж имен аргументов, которые принимает макрос.
-
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>
<dt>Realname</dt>
<dd>{{ user.realname|e }}</dd>
<dt>Description</dt>
<dd>{{ user.description }}</dd>
</dl>
{% endcall %}
Фильтры
Разделы фильтров позволяют применять обычные фильтры Jinja к блоку данных шаблона. Просто оберните код в специальный раздел filter:
{% filter upper %}
This text becomes uppercase
{% endfilter %}
Присваивания
Внутри блоков кода также можно присваивать значения переменным. Присваивания на верхнем уровне (вне блоков, макросов или циклов) экспортируются из шаблона как макросы верхнего уровня и могут быть импортированы другими шаблонами.
Присваивания используют тег set и могут иметь несколько целевых объектов:
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}
Поведение области видимости
Пожалуйста, помните, что невозможно установить переменные внутри блока и отобразить их вне его. Это также относится к циклам. Исключение составляют условные операторы if, которые не вводят область видимости. В результате следующий шаблон не сделает того, чего вы ожидаете:
{% set iterated = false %}
{% for item in seq %}
{{ item }}
{% set iterated = true %}
{% endfor %}
{% if not iterated %} did not iterate {% endif %}
Это невозможно в синтаксисе Jinja. Вместо этого используйте альтернативные конструкции, такие как блок else в цикле или специальную переменную loop:
{% for item in seq %}
{{ item }}
{% else %}
did not iterate
{% endfor %}
Начиная с версии 2.10, более сложные случаи могут быть обработаны с помощью объектов пространства имен, которые позволяют распространять изменения через области видимости:
{% set ns = namespace(found=false) %}
{% for item in items %}
{% if item.check_something() %}
{% set ns.found = true %}
{% endif %}
* {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
Обратите внимание, что запись obj.attr в теге set разрешена только для объектов пространства имен; попытка присвоить атрибут любому другому объекту вызовет исключение.
Журнал изменений
В версии 2.10: Добавлена поддержка объектов пространства имен
Блочные присваивания
Журнал изменений
Новая версия с 2.8.
Начиная с Jinja 2.8, можно также использовать блочные присваивания для захвата содержимого блока в имя переменной. Это может быть полезно в некоторых ситуациях в качестве альтернативы макросам. В этом случае вместо использования знака равенства и значения просто запишите имя переменной, а затем всё до {% endset %} будет захвачено.
Пример:
{% set navigation %}
<li><a href="/">Index</a>
<li><a href="/downloads">Downloads</a>
{% endset %}
Переменная navigation затем содержит исходный код навигации HTML.
Журнал изменений
Изменено в версии 2.10.
Начиная с Jinja 2.10, блочное присваивание поддерживает фильтры.
Пример:
{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}
Расширение
Тэг extends можно использовать для расширения одного шаблона из другого. Вы можете иметь несколько тегов extends в файле, но только один из них может быть выполнен за раз.
См. раздел о Наследовании шаблонов выше.
Блоки
Блоки используются для наследования и действуют как заглушки и замены одновременно. Подробное описание приведено в разделе Наследование шаблонов.
Включение
Тэг include полезен для включения шаблона и возвращения отрендеренного содержимого этого файла в текущее пространство имен:
{% include 'header.html' %}
Body
{% 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.
Импорт
Jinja поддерживает размещение часто используемого кода в макросах. Эти макросы могут быть помещены в разные шаблоны и импортированы оттуда. Это работает аналогично операторам импорта в Python. Важно знать, что импорты кэшируются, и импортированные шаблоны не имеют доступа к переменным текущего шаблона, только к глобальным переменным по умолчанию. Более подробную информацию о поведении контекста импорта и включения см. в разделе Поведение контекста импорта.
Существует два способа импорта шаблонов. Вы можете импортировать весь шаблон в переменную или запросить конкретные макросы/экспортированные переменные из него.
Представьте, что у нас есть вспомогательный модуль, который рендерит формы (называется forms.html):
{% macro input(name, value='', type='text') -%}
<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
}}">{{ value|e }}</textarea>
{%- endmacro %}
Самый простой и гибкий способ доступа к переменным и макросам шаблона — импортировать весь модуль шаблона в переменную. Таким образом, вы можете получить доступ к атрибутам:
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
В качестве альтернативы вы можете импортировать определенные имена из шаблона в текущее пространство имен:
{% from 'forms.html' import input as input_field, textarea %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>
Макросы и переменные, начинающиеся с одного или нескольких символов нижнего подчеркивания, являются закрытыми и не могут быть импортированы.
Журнал изменений
Изменено в версии 2.4: Если в контекст шаблона был передан объект шаблона, вы можете импортировать из этого объекта.
Поведение контекста импорта
По умолчанию включенные шаблоны получают текущий контекст, а импортированные — нет. Причина в том, что импорты, в отличие от включений, кэшируются; импорты часто используются просто как модули, содержащие макросы.
Это поведение можно явно изменить: добавив with context или without context к директиве импорта/включения, текущий контекст может быть передан шаблону, и кэширование автоматически отключено.
Вот два примера:
{% 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 / 123_456 -
Целые числа — это целые числа без дробной части. Символ «_» может использоваться для разделения групп для повышения читабельности.
-
42.23 / 42.1e2 / 123_456.789 -
Числа с плавающей точкой могут быть записаны с использованием «.» в качестве десятичной точки. Они также могут быть записаны в экспоненциальной форме с использованием заглавной или строчной буквы «e» для указания части экспоненты. Символ «_» может использоваться для разделения групп для повышения читабельности, но не может использоваться в части экспоненты.
-
['list', 'of', 'objects'] -
Всё между двумя скобками является списком. Списка полезны для хранения последовательных данных, которые нужно обрабатывать циклом. Например, вы можете легко создать список ссылок, используя списки и кортежи для (и со) цикла for:
<ul> {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), ('downloads.html', 'Downloads')] %} <li><a href="{{ href }}">{{ caption }}</a></li> {% endfor %} </ul> -
('tuple', 'of', 'values') -
Кортежи похожи на списки, но не могут быть изменены («неизменяемые»). Если кортеж содержит только один элемент, за ним должен следовать запятая (
('1-tuple',)). Кортежи обычно используются для представления элементов из двух или более элементов. Более подробную информацию см. в примере списка выше. -
{'dict': 'of', 'key': 'and', 'value': 'pairs'} -
Словарь (dict) в 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, если левое и правое операнды истинны.
-
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 -
Выполняет тест.
-
| (pipe, vertical bar) -
Применяет фильтр.
-
~ (tilde) -
Преобразует все операнды в строки и конкатенирует их.
{{ "Hello " ~ name ~ "!" }}вернёт (предполагая, чтоnameустановлено в'John')Hello John!. -
() -
Вызов вызываемого объекта:
{{ post.render() }}. В скобках можно использовать позиционные и именованные аргументы, как и в Python:{{ post.render(user, full=true) }}. -
. / [] -
Получение атрибута объекта. (См. Переменные)
Выражение if
Также можно использовать встроенные выражения if. Они полезны в некоторых ситуациях. Например, вы можете использовать его для расширения одного шаблона, если переменная определена, в противном случае — из шаблона по умолчанию:
{% extends layout_template if layout_template is defined else 'default.html' %}
Общая синтаксис: <do something> if <something is true> else <do
something else>.
Часть else необязательна. Если она не указана, блок else неявно оценивается как объект Undefined (независимо от того, что undefined в среде установлено):
{{ "[{}]".format(page.title) if page.title }}
Методы Python
Вы также можете использовать любой метод, определённый для типа переменной. Возвращаемое значение вызова метода используется в качестве значения выражения. Вот пример, который использует методы, определённые для строк (где page.title — строка):
{{ page.title.capitalize() }}
Это работает для методов пользовательских типов. Например, если переменная f типа Foo имеет метод bar, вы можете сделать следующее:
{{ f.bar(value) }}
Методы операторов также работают как ожидается. Например, % реализует форматирование строк в стиле printf:
{{ "Hello, %s!" % name }}
Хотя предпочтительнее использовать метод .format в этом случае (который немного искусственный в контексте рендеринга шаблона):
{{ "Hello, {}!".format(name) }}
Список встроенных фильтров
-
jinja-filters.abs(x, /) -
Возвращает абсолютное значение аргумента.
-
jinja-filters.attr(obj: Any, name: str) → Union[jinja2.runtime.Undefined, Any] -
Получает атрибут объекта.
foo|attr("bar")работает какfoo.bar, но всегда возвращает атрибут, а не ищет элементы.См. Примечания по подпискам для получения более подробной информации.
-
jinja-filters.batch(value: ‘t.Iterable[V]’, linecount: int, fill_with: ‘t.Optional[V]’ = None) → ’t.Iterator[t.List[V]]’ -
Фильтр, который разбивает элементы на группы. Он работает практически так же, как
slice, только в обратном порядке. Он возвращает список списков с заданным количеством элементов. Если вы предоставите второй параметр, он используется для заполнения отсутствующих элементов. Посмотрите этот пример:<table> {%- for row in items|batch(3, ' ') %} <tr> {%- for column in row %} <td>{{ column }}</td> {%- endfor %} </tr> {%- endfor %} </table>
-
jinja-filters.capitalize(s: str) →str -
Преобразует значение в строку с заглавной первой буквой и строчными остальными.
-
jinja-filters.center(value: str, width: int = 80) →str -
Центрирует значение в поле заданной ширины.
-
jinja-filters.default(value: ~ V, default_value: ~ V = '', boolean: bool = False) → ~V -
Если значение не определено, то возвращает переданное значение по умолчанию, иначе значение переменной:
{{ my_variable|default('my_variable is not defined') }}Это выведет значение
my_variable, если переменная была определена, иначе'my_variable is not defined'. Если вы хотите использовать значение по умолчанию для переменных, оцениваемых как ложные, вам нужно установить второй параметр наtrue:{{ ''|default('the string was empty', true) }}Changelog
Изменено в версии 2.11: Теперь можно настроить
EnvironmentсChainableUndefined, чтобы фильтрdefaultработал с вложенными элементами и атрибутами, которые могут содержать неопределённые значения в цепочке, без полученияUndefinedError.- Псевдонимы
-
d
-
jinja-filters.dictsort(value: Mapping[~ K, ~ V], case_sensitive: bool = False, by: ‘te.Literal[“key”, “value”]’ = 'key', reverse: bool = False) → List[Tuple[~K, ~V]] -
Сортирует словарь и возвращает пары (ключ, значение). Словари Python могут не быть отсортированы в порядке, в котором вы хотите их отобразить, поэтому отсортируйте их предварительно.
{% for key, value in mydict|dictsort %} sort the dict by key, case insensitive {% for key, value in mydict|dictsort(reverse=true) %} sort the dict by key, case insensitive, reverse order {% for key, value in mydict|dictsort(true) %} sort the dict by key, case sensitive {% for key, value in mydict|dictsort(false, 'value') %} sort the dict by value, case insensitive
-
jinja-filters.escape(value) -
Заменяет символы
&,<,>,'и"в строке на безопасные для HTML последовательности. Используйте это, если вам нужно отобразить текст, который может содержать такие символы в HTML.Если у объекта есть метод
__html__, он вызывается, и предполагается, что возвращаемое значение уже безопасно для HTML.- Параметры
-
s – Объект, который нужно преобразовать в строку и экранировать.
- Возвращает
-
Строку
Markupс экранированным текстом. - Псевдонимы
-
e
-
jinja-filters.filesizeformat(value: Union[str, float, int], binary: bool = False) →str -
Форматирует значение как «человекопонятный» размер файла (например, 13 КБ, 4,1 МБ, 102 байта и т. д.). По умолчанию используются десятичные префиксы (Мега, Гига и т. д.), если второй параметр установлен в
True, используются двоичные префиксы (Мэби, Гиби).
-
jinja-filters.first(seq: ‘t.Iterable[V]’) → ’t.Union[V, Undefined]’ -
Возвращает первый элемент последовательности.
-
jinja-filters.float(value: Any, default: float = 0.0) →float -
Преобразует значение в число с плавающей точкой. Если преобразование не выполняется, возвращается
0.0. Это значение можно переопределить, используя первый параметр.
-
jinja-filters.forceescape(value: ‘t.Union[str, HasHTML]’) → markupsafe.Markup -
Вынужденное экранирование HTML. Скорее всего, произойдет двойное экранирование переменных.
-
jinja-filters.format(value: str, *args: Any, **kwargs: Any) →str -
Применяет заданные значения к строке форматирования в стиле printf, например
string % values.{{ "%s, %s!"|format(greeting, name) }} Hello, World!В большинстве случаев более удобным и эффективным будет использование оператора
%илиstr.format().{{ "%s, %s!" % (greeting, name) }} {{ "{}, {}!".format(greeting, name) }}
-
jinja-filters.groupby(value: ‘t.Iterable[V]’, attribute: Union[str, int], default: Union[Any, NoneType] = None) → ’t.List[t.Tuple[t.Any, t.List[V]]]’ -
Группирует последовательность объектов по атрибуту, используя функцию Python
itertools.groupby(). Атрибут может использовать нотацию точки для вложенного доступа, например"address.city". В отличие от функции Pythongroupby, значения сортируются сначала, поэтому для каждого уникального значения возвращается только одна группа.Например, список объектов
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>Можно указать значение
default, которое будет использоваться, если у объекта в списке отсутствует указанный атрибут.<ul>{% for city, items in users|groupby("city", default="NY") %} <li>{{ city }}: {{ items|map(attribute="name")|join(", ") }}</li> {% endfor %}</ul>Изменено в версии 3.0: Добавлен параметр
default.Изменения
Изменено в версии 2.6: Атрибут поддерживает нотацию точки для вложенного доступа.
-
jinja-filters.indent(s: str, width: Union[int, str] = 4, first: bool = False, blank: bool = False) →str -
Возвращает копию строки, где каждая строка отступает на 4 пробела. Первая строка и пустые строки по умолчанию не отступаются.
- Параметры
-
- width – Количество пробелов или строка для отступа.
- first – Не пропускать отступ первой строки.
- blank – Не пропускать отступ пустых строк.
Изменено в версии 3.0:
widthможет быть строкой.Изменения
Изменено в версии 2.10: Пустые строки не отступаются по умолчанию.
Переименовано аргумент
indentfirstвfirst.
-
jinja-filters.int(value: Any, default: int = 0, base: int = 10) →int -
Преобразует значение в целое число. Если преобразование не выполняется, возвращается
0. Можно переопределить значение по умолчанию с помощью первого параметра. Также можно переопределить значение по умолчанию базы (10) с помощью второго параметра, который обрабатывает входные данные с префиксами, такими как 0b, 0o и 0x для баз 2, 8 и 16 соответственно. База игнорируется для десятичных чисел и значений, не являющихся строками.
-
jinja-filters.join(value: Iterable, d: str = '', attribute: Union[str, int, NoneType] = None) →str -
Возвращает строку, являющуюся конкатенацией строк в последовательности. Разделитель между элементами по умолчанию пустая строка, вы можете его определить с помощью необязательного параметра:
{{ [1, 2, 3]|join('|') }} -> 1|2|3 {{ [1, 2, 3]|join }} -> 123Также возможно объединить определённые атрибуты объекта:
{{ users|join(', ', attribute='username') }}Изменения
Введено в версии 2.6: Добавлен параметр
attribute.
-
jinja-filters.last(seq: ‘t.Reversible[V]’) → ’t.Union[V, Undefined]’ -
Возвращает последний элемент последовательности.
Примечание: Не работает с генераторами. Возможно, вы захотите явным образом преобразовать его в список:
{{ data | selectattr('name', '==', 'Jinja') | list | last }}
-
jinja-filters.length(obj, /) -
Возвращает количество элементов в контейнере.
- Псевдонимы
-
count
-
jinja-filters.list(value: ‘t.Iterable[V]’) → ’t.List[V]’ -
Преобразует значение в список. Если это была строка, возвращаемый список будет списком символов.
-
jinja-filters.lower(s: str) →str -
Преобразует значение в нижний регистр.
-
jinja-filters.map(value: Iterable, *args: Any, **kwargs: Any) → Iterable -
Применяет фильтр к последовательности объектов или ищет атрибут. Это полезно при работе со списками объектов, но вас интересует только определённое значение.
Основное использование — отображение атрибута. Представьте, у вас есть список пользователей, но вам нужен только список имён пользователей:
Users on this page: {{ users|map(attribute='username')|join(', ') }}Можно указать значение
default, которое будет использоваться, если у объекта в списке отсутствует указанный атрибут.{{ users|map(attribute="username", default="Anonymous")|join(", ") }}В качестве альтернативы, вы можете позволить ему вызвать фильтр, передав имя фильтра и последующие аргументы. Хорошим примером будет применение фильтра преобразования текста к последовательности:
Users on this page: {{ titles|map('lower')|join(', ') }}Аналогично генераторному выражению:
(u.username for u in users) (getattr(u, "username", "Anonymous") for u in users) (do_lower(x) for x in titles)
Изменения
Изменено в версии 2.11.0: Добавлен параметр
default.Введено в версии 2.7.
-
jinja-filters.max(value: ‘t.Iterable[V]’, case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) → ’t.Union[V, Undefined]’ -
Возвращает наибольший элемент из последовательности.
{{ [1, 2, 3]|max }} -> 3- Параметры
-
- case_sensitive – Учитывать регистр больших и малых букв в строках.
- attribute – Получить объект с максимальным значением этого атрибута.
-
jinja-filters.min(value: ‘t.Iterable[V]’, case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) → ’t.Union[V, Undefined]’ -
Возвращает наименьший элемент из последовательности.
{{ [1, 2, 3]|min }} -> 1- Параметры
-
- case_sensitive – Учитывать регистр больших и малых букв в строках.
- attribute – Получить объект с минимальным значением этого атрибута.
-
jinja-filters.pprint(value: Any) →str -
Красивая печать переменной. Полезно для отладки.
-
jinja-filters.random(seq: ‘t.Sequence[V]’) → ’t.Union[V, Undefined]’ -
Возвращает случайный элемент из последовательности.
-
jinja-filters.reject(value: ‘t.Iterable[V]’, *args: Any, **kwargs: Any) → ’t.Iterator[V]’ -
Фильтрует последовательность объектов, применяя тест к каждому объекту и отбрасывая объекты, для которых тест успешен.
Если тест не указан, каждый объект оценивается как булево значение.
Пример использования:
{{ numbers|reject("odd") }}Аналогично генераторному выражению:
(n for n in numbers if not test_odd(n))
Изменения
Введено в версии 2.7.
-
jinja-filters.rejectattr(value: ‘t.Iterable[V]’, *args: Any, **kwargs: Any) → ’t.Iterator[V]’ -
Фильтрует последовательность объектов, применяя тест к указанному атрибуту каждого объекта и отбрасывая объекты, для которых тест успешен.
Если тест не указан, значение атрибута оценивается как булево значение.
{{ users|rejectattr("is_active") }} {{ users|rejectattr("email", "none") }}Аналогично генераторному выражению:
(u for user in users if not user.is_active) (u for user in users if not test_none(user.email))
Изменения
Введено в версии 2.7.
-
jinja-filters.replace(s: str, old: str, new: str, count: Union[int, NoneType] = None) →str -
Возвращает копию значения со всеми вхождениями подстроки, замененными новой. Первый аргумент — подстрока, которая должна быть заменена, второй — строка замены. Если необязательный третий аргумент
countзадан, заменяются только первыеcountвхождения:{{ "Hello World"|replace("Hello", "Goodbye") }} -> Goodbye World {{ "aaaaargh"|replace("a", "d'oh, ", 2) }} -> d'oh, d'oh, aaargh
-
jinja-filters.reverse(value: Union[str, Iterable[~ V]]) → Union[str, Iterable[~V]] -
Инвертирует объект или возвращает итератор, который итерирует в обратном порядке.
-
jinja-filters.round(value: float, precision: int = 0, method: ‘te.Literal[“common”, “ceil”, “floor”]’ = 'common') →float -
Округляет число до заданной точности. Первый параметр задаёт точность (по умолчанию
0), второй — метод округления:-
'common'округляет вверх или вниз -
'ceil'всегда округляет вверх -
'floor'всегда округляет вниз
Если метод не указан, используется
'common'.{{ 42.55|round }} -> 43.0 {{ 42.55|round(1, 'floor') }} -> 42.5Обратите внимание, что даже при округление до 0 точности, возвращается число с плавающей точкой. Если вам нужен настоящий целое число, используйте
int:{{ 42.55|round|int }} -> 43 -
-
jinja-filters.safe(value: str) → markupsafe.Markup -
Помечает значение как безопасное, что означает, что в среде с автоматическим экранированием эта переменная не будет экранироваться.
-
jinja-filters.select(value: ‘t.Iterable[V]’, *args: Any, **kwargs: Any) → ’t.Iterator[V]’ -
Фильтрует последовательность объектов, применяя к каждому объекту проверку, и выбирает только объекты, для которых проверка успешна.
Если проверка не указана, каждый объект будет оцениваться как булево значение.
Пример использования:
{{ numbers|select("odd") }} {{ numbers|select("odd") }} {{ numbers|select("divisibleby", 3) }} {{ numbers|select("lessthan", 42) }} {{ strings|select("equalto", "mystring") }}Аналогично генераторному выражению:
(n for n in numbers if test_odd(n)) (n for n in numbers if test_divisibleby(n, 3))
Changelog
Добавлено в версии 2.7.
-
jinja-filters.selectattr(value: ‘t.Iterable[V]’, *args: Any, **kwargs: Any) → ’t.Iterator[V]’ -
Фильтрует последовательность объектов, применяя проверку к указанному атрибуту каждого объекта и выбирает только объекты, для которых проверка успешна.
Если проверка не указана, значение атрибута будет оцениваться как булево значение.
Пример использования:
{{ users|selectattr("is_active") }} {{ users|selectattr("email", "none") }}Аналогично генераторному выражению:
(u for user in users if user.is_active) (u for user in users if test_none(user.email))
Changelog
Добавлено в версии 2.7.
-
jinja-filters.slice(value: ‘t.Collection[V]’, slices: int, fill_with: ‘t.Optional[V]’ = None) → ’t.Iterator[t.List[V]]’ -
Разбивает итератор и возвращает список списков, содержащих эти элементы. Полезно, если нужно создать div, содержащий три тега ul, которые представляют колонки:
<div class="columnwrapper"> {%- for column in items|slice(3) %} <ul class="column-{{ loop.index }}"> {%- for item in column %} <li>{{ item }}</li> {%- endfor %} </ul> {%- endfor %} </div>Если вы передадите второй аргумент, он будет использован для заполнения пропущенных значений на последней итерации.
-
jinja-filters.sort(value: ‘t.Iterable[V]’, reverse: bool = False, case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) → ’t.List[V]’ -
Сортирует итерируемый объект, используя 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 %}Changelog
Изменено в версии 2.11.0: Параметр
attributeможет быть списком атрибутов, разделённых запятыми, например,"age,name".Изменено в версии 2.6: Добавлен параметр
attribute.
-
jinja-filters.string(value) -
Преобразует объект в строку, если он ещё не является строкой. Это сохраняет строку
Markup, а не преобразует её обратно в обычную строку, поэтому она всё ещё будет помечена как безопасная и не будет повторно экранироваться.>>> value = escape("<User 1>") >>> value Markup('<User 1>') >>> escape(str(value)) Markup('&lt;User 1&gt;') >>> escape(soft_str(value)) Markup('<User 1>')
-
jinja-filters.striptags(value: ‘t.Union[str, HasHTML]’) →str -
Удаляет теги SGML/XML и заменяет последовательные пробелы одним пробелом.
-
jinja-filters.sum(iterable: ‘t.Iterable[V]’, attribute: Union[str, int, NoneType] = None, start: ~ V = 0) → ~V -
Возвращает сумму последовательности чисел плюс значение параметра 'start' (по умолчанию 0). Если последовательность пустая, возвращает start.
Также можно суммировать только определённые атрибуты:
Total: {{ items|sum(attribute='price') }}Changelog
Изменено в версии 2.6: Добавлен параметр
attributeдля суммирования по атрибутам. Также параметрstartбыл перемещён вправо.
-
jinja-filters.title(s: str) →str -
Возвращает заголовок, представляющий значение. То есть слова будут начинаться с заглавных букв, а все остальные символы — строчные.
-
jinja-filters.tojson(value: Any, indent: Union[int, NoneType] = None) → markupsafe.Markup -
Сериализует объект в строку JSON и помечает её как безопасную для рендеринга в HTML. Этот фильтр предназначен только для использования в HTML-документах.
Возвращаемая строка безопасна для рендеринга в HTML-документах и
<script>тегах. Исключением являются HTML-атрибуты, которые заключены в двойные кавычки; используйте одинарные кавычки или фильтр|forceescape.- Параметры
-
- value – Объект для сериализации в JSON.
-
indent – Параметр
indent, переданный вdumps, для красивого форматирования значения.
Changelog
Добавлено в версии 2.9.
-
jinja-filters.trim(value: str, chars: Union[str, NoneType] = None) →str -
Удаляет начальные и конечные символы, по умолчанию — пробелы.
-
jinja-filters.truncate(s: str, length: int = 255, killwords: bool = False, end: str = '...', leeway: Union[int, NoneType] = None) →str -
Возвращает усечённую копию строки. Длина задаётся первым параметром, по умолчанию равным
255. Если второй параметр равенtrue, фильтр обрежет текст по длине. В противном случае он отбросит последнее слово. Если текст был усечён, он добавит многоточие ("..."). Если нужно другое многоточие, чем"...", можно указать его в третьем параметре. Строки, которые превышают длину только на величину допуска, указанного в четвёртом параметре, не будут усечены.{{ "foo bar baz qux"|truncate(9) }} -> "foo..." {{ "foo bar baz qux"|truncate(9, True) }} -> "foo ba..." {{ "foo bar baz qux"|truncate(11) }} -> "foo bar baz qux" {{ "foo bar baz qux"|truncate(11, False, '...', 0) }} -> "foo bar..."По умолчанию допуск в новых версиях Jinja составляет 5, а в предыдущих — 0, но его можно настроить глобально.
-
jinja-filters.unique(value: ‘t.Iterable[V]’, case_sensitive: bool = False, attribute: Union[str, int, NoneType] = None) → ’t.Iterator[V]’ -
Возвращает список уникальных элементов из данного итерируемого объекта.
{{ ['foo', 'bar', 'foobar', 'FooBar']|unique|list }} -> ['foo', 'bar', 'foobar']Уникальные элементы выдаются в том же порядке, в котором они впервые встречаются в итерируемом объекте, переданном в фильтр.
- Параметры
-
- case_sensitive – Считать строчные и прописные буквы различными.
- attribute – Фильтровать объекты с уникальными значениями для этого атрибута.
-
jinja-filters.upper(s: str) →str -
Преобразует значение в верхний регистр.
-
jinja-filters.urlencode(value: Union[str, Mapping[str, Any], Iterable[Tuple[str, Any]]]) →str -
Кодирует данные для использования в URL-пути или запросе, используя UTF-8.
Основной обёрткой вокруг
urllib.parse.quote()при передаче строки илиurllib.parse.urlencode()для словаря или итерируемого объекта.- Параметры
-
value – Данные для кодирования. Строка будет закодирована непосредственно. Словарь или итерируемый объект пар
(key, value)будут объединены как строка запроса.
Когда передаётся строка, “/” не кодируется. Веб-серверы обрабатывают “/” и “%2F” как эквивалентные символы в путях. Если вам нужны закодированные слэши, используйте фильтр
|replace("/", "%2F").Changelog
Добавлено в версии 2.7.
-
jinja-filters.urlize(value: str, trim_url_limit: Union[int, NoneType] = None, nofollow: bool = False, target: Union[str, NoneType] = None, rel: Union[str, NoneType] = None, extra_schemes: Union[Iterable[str], NoneType] = None) →str -
Преобразовать URL-адреса в тексте в кликабельные ссылки.
В некоторых ситуациях ссылки могут не распознаваться. Обычно для более глубокой обработки ссылок лучше использовать более сложный форматтер, например, библиотеку Markdown.
Функция работает с
http://,https://,www.,mailto:и адресами электронной почты. Ссылки с заключительной пунктуацией (точками, запятыми, закрывающими скобками) и начальной пунктуацией (открывающими скобками) распознаются, за исключением пунктуации. Адреса электронной почты, содержащие заголовки, не распознаются (например,mailto:address@example.com?cc=copy@example.com).- Параметры
-
- значение – Исходный текст, содержащий URL-адреса, которые нужно связать.
- trim_url_limit – Укоротить отображаемые значения URL до этого ограничения.
-
nofollow – Добавить атрибут
rel=nofollowк ссылкам. -
target – Добавить атрибут
targetк ссылкам. -
rel – Добавить атрибут
relк ссылкам. -
extra_schemes – Распознавать URL-адреса, начинающиеся с этих схем помимо стандартного поведения. По умолчанию
env.policies["urlize.extra_schemes"], что по умолчанию означает отсутствие дополнительных схем.
Изменено в версии 3.0: Добавлен параметр
extra_schemes.Изменено в версии 3.0: Генерировать ссылки
https://для URL-адресов без схемы.Изменено в версии 3.0: Правила разбора были обновлены. Распознавать адреса электронной почты со схемой или без схемы
mailto:. Проверять IP-адреса. Игнорировать скобки и квадратные скобки в большем количестве случаев.Журнал изменений
Изменено в версии 2.8: Добавлен параметр
target.
-
jinja-filters.wordcount(s: str) →int -
Подсчитать слова в строке.
-
jinja-filters.wordwrap(s: str, width: int = 79, break_long_words: bool = True, wrapstring: Union[str, NoneType] = None, break_on_hyphens: bool = True) →str -
Обёртывание строки до заданной ширины. Существующие символы новой строки обрабатываются как абзацы, которые необходимо обёртывать по отдельности.
- Параметры
-
- s – Исходный текст для обёртывания.
- width – Максимальная длина обёрнутых строк.
-
break_long_words – Если слово длиннее
width, разбить его на строки. - break_on_hyphens – Если слово содержит дефисы, его можно разбить на строки.
-
wrapstring – Строка для соединения каждой обёрнутой строки. По умолчанию
Environment.newline_sequence.
Журнал изменений
Изменено в версии 2.11: Существующие символы новой строки обрабатываются как абзацы, которые необходимо обёртывать по отдельности.
Изменено в версии 2.11: Добавлен параметр
break_on_hyphens.Изменено в версии 2.7: Добавлен параметр
wrapstring.
-
jinja-filters.xmlattr(d: Mapping[str, Any], autospace: bool = True) →str -
Создание строки атрибутов SGML/XML на основе элементов в словаре. Все значения, которые не являются
noneилиundefined, автоматически экранируются:<ul{{ {'class': 'my_list', 'missing': none, 'id': 'list-%d'|format(variable)}|xmlattr }}> ... </ul>Результат примерно такой:
<ul class="my_list" id="list-42"> ... </ul>
Как видно, перед элементом автоматически добавляется пробел, если фильтр возвратил что-то, если только второй параметр не равен false.
Список встроенных тестов
-
jinja-tests.boolean(value: Any) →bool -
Возвращает True, если объект является булевым значением.
Изменения
Введено в версии 2.11.
-
jinja-tests.callable(obj, /) -
Возвращает True, если объект вызываемый (например, функция).
Обратите внимание, что классы вызываемые, как и экземпляры классов с методом __call__.
-
jinja-tests.defined(value: Any) →bool -
Возвращает True, если переменная определена:
{% if variable is defined %} value of variable: {{ variable }} {% else %} variable is not defined {% endif %}См. фильтр
default()для простого способа установки неопределенных переменных.
-
jinja-tests.divisibleby(value: int, num: int) →bool -
Проверяет, делится ли переменная на число без остатка.
-
jinja-tests.eq(a, b, /) -
То же самое, что и a == b.
- Псевдонимы
-
==,equalto
-
jinja-tests.escaped(value: Any) →bool -
Проверяет, является ли значение экранированным.
-
jinja-tests.even(value: int) →bool -
Возвращает True, если переменная является чётной.
-
jinja-tests.false(value: Any) →bool -
Возвращает True, если объект равен False.
Изменения
Введено в версии 2.11.
-
jinja-tests.filter(value: str) →bool -
Проверяет, существует ли фильтр по имени. Полезно, если фильтр может быть необязательно доступен.
{% if 'markdown' is filter %} {{ value | markdown }} {% else %} {{ value }} {% endif %}Введено в версии 3.0.
-
jinja-tests.float(value: Any) →bool -
Возвращает True, если объект является числом с плавающей точкой.
Изменения
Введено в версии 2.11.
-
jinja-tests.ge(a, b, /) -
То же самое, что и a >= b.
- Псевдонимы
-
>=
-
jinja-tests.gt(a, b, /) -
То же самое, что и a > b.
- Псевдонимы
-
>,greaterthan
-
jinja-tests.in(value: Any, seq: Container) →bool -
Проверяет, содержится ли значение в seq.
Изменения
Введено в версии 2.10.
-
jinja-tests.integer(value: Any) →bool -
Возвращает True, если объект является целым числом.
Изменения
Введено в версии 2.11.
-
jinja-tests.iterable(value: Any) →bool -
Проверяет, можно ли перебрать объект.
-
jinja-tests.le(a, b, /) -
То же самое, что и a <= b.
- Псевдонимы
-
<=
-
jinja-tests.lower(value: str) →bool -
Возвращает True, если переменная приведена к нижнему регистру.
-
jinja-tests.lt(a, b, /) -
То же самое, что и a < b.
- Псевдонимы
-
<,lessthan
-
jinja-tests.mapping(value: Any) →bool -
Возвращает True, если объект является словарем (dict и т.п.).
Изменения
Введено в версии 2.6.
-
jinja-tests.ne(a, b, /) -
То же самое, что и a != b.
- Псевдонимы
-
!=
-
jinja-tests.none(value: Any) →bool -
Возвращает True, если переменная равна None.
-
jinja-tests.number(value: Any) →bool -
Возвращает True, если переменная является числом.
-
jinja-tests.odd(value: int) →bool -
Возвращает True, если переменная является нечётной.
-
jinja-tests.sameas(value: Any, other: Any) →bool -
Проверяет, ссылается ли объект на тот же адрес памяти, что и другой объект:
{% if foo.attribute is sameas false %} the foo attribute really is the `False` singleton {% endif %}
-
jinja-tests.sequence(value: Any) →bool -
Возвращает True, если переменная является последовательностью. Последовательности — это переменные, которые можно перебирать.
-
jinja-tests.string(value: Any) →bool -
Возвращает True, если объект является строкой.
-
jinja-tests.test(value: str) →bool -
Проверяет, существует ли тест по имени. Полезно, если тест может быть необязательно доступен.
{% if 'loud' is test %} {% if value is loud %} {{ value|upper }} {% else %} {{ value|lower }} {% endif %} {% else %} {{ value }} {% endif %}Добавлена в версии 3.0.
-
jinja-tests.true(value: Any) →bool -
Возвращает True, если объект равен True.
Изменения
Добавлена в версии 2.11.
-
jinja-tests.undefined(value: Any) →bool -
Аналогично
defined(), но с обратным результатом.
-
jinja-tests.upper(value: str) →bool -
Возвращает True, если переменная записана в верхнем регистре.
Список глобальных функций
По умолчанию доступны следующие функции во всем глобальном пространстве имён:
-
jinja-globals.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>
-
jinja-globals.lipsum(n=5, html=True, min=20, max=100) -
Генерирует lorem ipsum для шаблона. По умолчанию генерируются пять абзацев HTML, причем каждый абзац содержит от 20 до 100 слов. Если html равен False, возвращается обычный текст. Это полезно для генерации простого содержимого для тестирования макета.
-
jinja-globals.dict(\**items) -
Удобная альтернатива литералам dict.
{'foo': 'bar'}эквивалентноdict(foo='bar').
-
class jinja-globals.cycler(\*items) -
Перебирает значения, возвращая их по одному, а затем перезапускается, когда достигается конец.
Аналогично
loop.cycle, но может использоваться вне циклов или в нескольких циклах. Например, отобразите список папок и файлов в списке, чередуя им классы «нечётный» и «чётный».{% set row_class = cycler("odd", "even") %} <ul class="browser"> {% for folder in folders %} <li class="folder {{ row_class.next() }}">{{ folder }} {% endfor %} {% for file in files %} <li class="file {{ row_class.next() }}">{{ file }} {% endfor %} </ul>- Параметры
-
items – Каждый позиционный аргумент будет возвращён в заданном порядке для каждого цикла.
Изменения
Добавлена в версии 2.1.
-
property current -
Возвращает текущий элемент. Эквивалентно элементу, который будет возвращён при следующем вызове
next().
-
next() -
Возвращает текущий элемент, а затем перемещает
currentк следующему элементу.
-
reset() -
Сбрасывает текущий элемент на первый элемент.
-
class jinja-globals.joiner(sep=', ') -
Небольшая утилита, которая может использоваться для «объединения» нескольких секций. Объединителю передаётся строка, и он будет возвращать эту строку каждый раз, за исключением первого раза (в первом случае он возвращает пустую строку). Можно использовать для объединения элементов:
{% set pipe = joiner("|") %} {% if categories %} {{ pipe() }} Categories: {{ categories|join(", ") }} {% endif %} {% if author %} {{ pipe() }} Author: {{ author() }} {% endif %} {% if can_edit %} {{ pipe() }} <a href="?action=edit">Edit</a> {% endif %}Изменения
Добавлена в версии 2.1.
-
class jinja-globals.namespace(...) -
Создаёт новый контейнер, который позволяет назначать атрибуты с помощью тега
{% set %}:{% set ns = namespace() %} {% set ns.foo = 'bar' %}Основное назначение этого — позволить переносить значение из тела цикла во внешнюю область видимости. Начальные значения можно задать как dict, как ключевые аргументы или и то, и другое (поведение аналогично конструктору Python
dict):{% set ns = namespace(found=false) %} {% for item in items %} {% if item.check_something() %} {% set ns.found = true %} {% endif %} * {{ item.title }} {% endfor %} Found item having something: {{ ns.found }}Изменения
Добавлена в версии 2.10.
Расширения
В следующих разделах рассматриваются встроенные расширения Jinja, которые могут быть включены приложением. Приложение также может предоставлять дополнительные расширения, не охваченные данной документацией; в этом случае должна быть отдельная документация, объясняющая указанные расширения.
Международная локализация (i18n)
Если расширение i18n включено, можно пометить текст в шаблоне как подлежащий переводу. Для того, чтобы пометить раздел как подлежащий переводу, используйте блок:
trans Внутри блока не допускаются операторы, только текст и простые теги переменных.
Теги переменных могут быть только именами, не доступом к атрибутам, фильтрами или другими выражениями. Чтобы использовать выражение, привяжите его к имени в теге trans для использования в блоке.
{% trans user=user.username %}Hello, {{ user }}!{% endtrans %}
Чтобы привязать более одного выражения, разделяйте их запятыми (,).
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}
Для множественного числа укажите форму единственного и множественного числа, разделив их тегом pluralize.
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
По умолчанию, первая переменная в блоке используется для определения того, использовать ли форму единственного или множественного числа. Если это неверно, укажите переменную, используемую для множественного числа, в качестве параметра к pluralize.
{% trans ..., user_count=users|length %}...
{% pluralize user_count %}...{% endtrans %}
При переводе блоков текста пробелы и переводы строк приводят к трудночитаемым и подверженным ошибкам строкам перевода. Чтобы избежать этого, блок trans можно пометить как обрезной, что заменит все переводы строк и пробелы вокруг них одним пробелом и удалит начальные и конечные пробелы.
{% trans trimmed book_title=book.title %}
This is {{ book_title }}.
You should read it!
{% endtrans %}
Это приводит к This is %(book_title)s. You should read it! в файле перевода.
Если обрезка включена глобально, можно использовать модификатор notrimmed для отключения ее для блока.
Журнал изменений
В версии 2.10: Добавлены модификаторы trimmed и notrimmed.
Можно переводить строки в выражениях с помощью этих функций:
-
gettext: перевести одну строку -
ngettext: перевести строку, допускающую множественное число -
_: псевдоним дляgettext
Можно вывести переведенную строку так:
{{ _("Hello, World!") }}
Для использования заглушек используйте фильтр format.
{{ _("Hello, %(user)s!")|format(user=user.username) }}
Всегда используйте именованные аргументы для format, так как другие языки могут не использовать слова в том же порядке.
Если вызовы Нового стиля Gettext активированы, использование заглушек становится проще. Форматирование является частью вызова gettext вместо использования фильтра format.
{{ gettext('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}
{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}
Строка формата функции ngettext автоматически получает счёт как параметр num в дополнение к заданным параметрам.
Оператор выражения
Если загружено расширение оператора выражения, доступен тег do, который работает точно так же, как обычное выражение переменной ({{ ... }}); за исключением того, что он ничего не выводит. Это можно использовать для изменения списков:
{% do navigation.append('a string') %}
Управление циклами
Если приложение включает Управление циклами, можно использовать break и continue в циклах. Когда достигается break, цикл завершается; если достигается continue, обработка останавливается и продолжается с следующей итерацией.
Вот цикл, пропускающий каждый второй элемент:
{% for user in users %}
{%- if loop.index is even %}{% continue %}{% endif %}
...
{% endfor %}
Аналогично, цикл, который останавливает обработку после 10-й итерации:
{% for user in users %}
{%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}
Обратите внимание, что loop.index начинается с 1, а loop.index0 начинается с 0 (см.: Для).
Оператор отладки
Если включено расширение Отладки, тег {% debug %} будет доступен для вывода текущего контекста, а также доступных фильтров и тестов. Это полезно для просмотра того, что доступно для использования в шаблоне, без настройки отладчика.
<pre>{% debug %}</pre>
{'context': {'cycler': <class 'jinja2.utils.Cycler'>,
...,
'namespace': <class 'jinja2.utils.Namespace'>},
'filters': ['abs', 'attr', 'batch', 'capitalize', 'center', 'count', 'd',
..., 'urlencode', 'urlize', 'wordcount', 'wordwrap', 'xmlattr'],
'tests': ['!=', '<', '<=', '==', '>', '>=', 'callable', 'defined',
..., 'odd', 'sameas', 'sequence', 'string', 'undefined', 'upper']}
Оператор with
Журнал изменений
В версии 2.3.
Оператор with позволяет создать новую внутреннюю область видимости. Переменные, заданные в этой области видимости, не видны за пределами этой области.
With вкратце:
{% with %}
{% set foo = 42 %}
{{ foo }} foo is 42 here
{% endwith %}
foo is not visible here any longer
Поскольку часто переменные задаются в начале области видимости, это можно сделать в операторе with. Следующие два примера эквивалентны:
{% with foo = 42 %}
{{ foo }}
{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}
{% endwith %}
Важный момент относительно областей видимости. В версиях Jinja до 2.9 поведение ссылки одной переменной на другую имело некоторые непреднамеренные последствия. В частности, одна переменная могла ссылаться на другую, определённую в том же операторе открытия блока with. Это вызывало проблемы с поведением очищенной области видимости и с тех пор было улучшено. В частности, в новых версиях Jinja следующий код всегда ссылается на переменную a извне блока with:
{% with a={}, b=a.attribute %}...{% endwith %}
В более ранних версиях Jinja атрибут b ссылался на результаты первого атрибута. Если вы полагаетесь на это поведение, вы можете переписать его, используя тег set:
{% with a={} %}
{% set b = a.attribute %}
{% endwith %}
Расширение
В более старых версиях Jinja (до 2.9) для активации этой функции требовалось включение расширения. Сейчас она включена по умолчанию.
Переопределения 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–2021 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/3.0.x/templates/
Комментарии
Для комментирования части строки в шаблоне используйте синтаксис комментария, который по умолчанию установлен в
{# ... #}. Это полезно для комментирования частей шаблона для отладки или добавления информации для других разработчиков шаблонов или для себя:{# note: commented-out template because we no longer use this {% for user in users %} ... {% endfor %} #}