Spec-Zone.ru › Jinja 2.9

API

В данном документе описывается API для Jinja2, а не язык шаблонов. Он будет наиболее полезен для тех, кто реализует интерфейс шаблонов в приложении, а не для тех, кто создаёт шаблоны Jinja2.

Основы

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

Большинство приложений создают один объект Environment при инициализации приложения и используют его для загрузки шаблонов. В некоторых случаях, однако, полезно иметь несколько сред, если используются разные конфигурации.

Самый простой способ настроить Jinja2 для загрузки шаблонов для вашего приложения выглядит примерно так:

from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
    loader=PackageLoader('yourapplication', 'templates'),
    autoescape=select_autoescape(['html', 'xml'])
)

Это создаст среду шаблонов с настройками по умолчанию и загрузчиком, который ищет шаблоны в папке templates внутри пакета yourapplication python. Доступны различные загрузчики, и вы также можете написать свой собственный, если хотите загружать шаблоны из базы данных или других ресурсов. Это также включает автоматическое экранирование для HTML- и XML-файлов.

Для загрузки шаблона из этой среды нужно просто вызвать метод get_template(), который затем возвращает загруженный Template:

template = env.get_template('mytemplate.html')

Чтобы отобразить его с некоторыми переменными, просто вызовите метод render():

print template.render(the='variables', go='here')

Использование загрузчика шаблонов вместо передачи строк в Template или Environment.from_string() имеет несколько преимуществ. Помимо того, что это намного проще в использовании, это также позволяет наследование шаблонов.

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

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

Unicode

Jinja2 использует Unicode внутри, что означает, что вам необходимо передавать объекты Unicode в функцию рендеринга или байтовые строки, состоящие только из символов ASCII. Кроме того, новые строки нормализуются до одного кода строки, который по умолчанию является стилем UNIX (\n).

Python 2.x поддерживает два способа представления строковых объектов. Один — тип str, а другой — тип unicode, оба из которых расширяют тип basestring. К сожалению, по умолчанию используется str, который не следует использовать для хранения текстовой информации, если не используются только символы ASCII. В Python 2.6 можно сделать unicode значением по умолчанию на уровне модуля, а в Python 3 это значение по умолчанию.

Чтобы явно использовать строку Unicode, необходимо префиксровать строковый литерал u: u'Hänsel und Gretel sagen Hallo'. Таким образом, Python сохранит строку в виде Unicode, декодируя строку с кодировкой символов из текущего модуля Python. Если кодировка не указана, по умолчанию используется «ASCII», что означает, что вы не можете использовать символы, не являющиеся ASCII.

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

# -*- coding: utf-8 -*-

Мы рекомендуем utf-8 в качестве кодировки для модулей Python и шаблонов, так как в utf-8 можно представить каждый символ Unicode, и он обратной совместим с ASCII. Для Jinja2 кодировка шаблонов по умолчанию предполагается utf-8.

Невозможно использовать Jinja2 для обработки не-Unicode данных. Причина в том, что Jinja2 уже использует Unicode на уровне языка. Например, Jinja2 рассматривает неразрывный пробел как допустимый пробел внутри выражений, что требует знания кодировки или работы со строкой Unicode.

Для получения более подробной информации об Unicode в Python см. отличную документацию по Unicode.

Ещё одним важным моментом является то, как Jinja2 обрабатывает строковые литералы в шаблонах. Примитивное решение — использовать строки Unicode для всех строковых литералов, но на практике оказалось, что это проблемно, так как некоторые библиотеки проверяют тип str явно. Например, datetime.strftime не принимает аргументы Unicode. Чтобы полностью этого не нарушить, Jinja2 возвращает str для строк, которые помещаются в ASCII, и для всего остального — unicode:

>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
>>> m.a
'foo'
>>> m.b
u'f\xf6\xf6'

Высокоуровневый API

Высокоуровневый API — это API, который вы будете использовать в приложении для загрузки и рендеринга шаблонов Jinja2. Низкоуровневый API, с другой стороны, полезен только если вы хотите глубже изучить Jinja2 или разрабатывать расширения.

class jinja2.Environment([options])

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

Вот возможные параметры инициализации:

block_start_string

Строка, обозначающая начало блока. По умолчанию '{%'.

block_end_string

Строка, обозначающая конец блока. По умолчанию '%}'.

variable_start_string

Строка, обозначающая начало оператора вывода. По умолчанию '{{'.

variable_end_string

Строка, обозначающая конец оператора вывода. По умолчанию '}}'.

comment_start_string

Строка, обозначающая начало комментария. По умолчанию '{#'.

comment_end_string

Строка, обозначающая конец комментария. По умолчанию '#}'.

line_statement_prefix

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

line_comment_prefix

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

Changelog

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

trim_blocks

Если это установлено в True, первая новая строка после блока удаляется (блок, а не тег переменной!). По умолчанию False.

lstrip_blocks

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

newline_sequence

Последовательность, которая запускает новую строку. Должна быть одной из '\r', '\n' или '\r\n'. По умолчанию '\n', что является удобным по умолчанию для систем Linux и OS X, а также веб-приложений.

keep_trailing_newline

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

Changelog

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

extensions

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

optimized

должен ли быть включён оптимизатор? Значение по умолчанию True.

undefined

Undefined или подкласс от него, используемый для представления неопределённых значений в шаблоне.

finalize

Вызываемый объект, который может использоваться для обработки результата выражения переменной перед выводом. Например, можно неявно преобразовать None в пустую строку здесь.

autoescape

Если установлено в True, функция автоматической экранизации XML/HTML включена по умолчанию. Для получения дополнительной информации об автоматической экранизации см. Markup. Начиная с Jinja 2.4, это также может быть вызываемый объект, которому передаётся имя шаблона и который должен возвращать True или False в зависимости от того, должна ли быть включена автоматическая экранизация по умолчанию.

Changelog

Изменено в версии 2.4: autoescape теперь может быть функцией

loader

Загрузчик шаблонов для этой среды.

cache_size

Размер кэша. По умолчанию это 400, что означает, что если загружено более 400 шаблонов, загрузчик очистит наименее используемый шаблон. Если размер кэша установлен в 0, шаблоны будут перекомпилироваться каждый раз, если размер кэша -1, кэш не будет очищен.

Changelog

Изменено в версии 2.8: Размер кэша был увеличен с 50 до 400.

auto_reload

Некоторые загрузчики загружают шаблоны из мест, где исходные тексты шаблонов могут изменяться (например, файловая система или база данных). Если auto_reload установлено в True (по умолчанию), каждый раз при запросе шаблона загрузчик проверяет, изменился ли источник, и если да, перезагрузит шаблон. Для повышения производительности можно отключить это.

bytecode_cache

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

См. Кэш байткода для получения дополнительной информации.

enable_async

Если установлено в true, это активирует асинхронную обработку шаблонов, что позволяет использовать новые возможности Python. Требуется Python 3.6 или новее.

shared

Если шаблон был создан с помощью конструктора Template, среда создаётся автоматически. Эти среды создаются как общие среды, что означает, что несколько шаблонов могут иметь одну и ту же анонимную среду. Для всех общих сред это свойство True, иначе False.

sandboxed

Если среда изолирована, это свойство True. Для режима изоляции ознакомьтесь с документацией по SandboxedEnvironment.

filters

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

tests

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

globals

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

policies

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

code_generator_class

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

context_class

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

overlay([options])

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

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

END_OF_DOCUMENT_MARKER
undefined([hint, obj, name, exc])

Создаёт новый объект Undefined для name. Это полезно для фильтров или функций, которые могут возвращать неопределённые объекты для некоторых операций. Все параметры, кроме hint, должны быть предоставлены в качестве именованных параметров для лучшей читаемости. hint используется в качестве сообщения об ошибке для исключения, если оно предоставлено, в противном случае сообщение об ошибке будет сгенерировано из obj и name автоматически. Предоставленное исключение exc генерируется, если с созданным неопределённым объектом выполняется действие, которое этот объект не допускает. По умолчанию используется исключение UndefinedError. Если предоставлено hint, name можно опустить.

Наиболее распространённый способ создания неопределённого объекта — это предоставление только имени:

return environment.undefined(name='some_name')

Это означает, что имя some_name не определено. Если имя получено из атрибута объекта, имеет смысл указать неопределённому объекту объект-владелец, чтобы улучшить сообщение об ошибке:

if not hasattr(obj, 'attr'):
    return environment.undefined(obj=obj, name='attr')

Для более сложных примеров можно предоставить подсказку. Например, фильтр first() создаёт неопределённый объект таким образом:

return environment.undefined('no first item, sequence was empty')

Если известно значение name или obj (например, потому что был обращён к атрибуту), его следует передать неопределённому объекту, даже если предоставлено пользовательское исключение hint. Это даёт неопределённым объектам возможность дополнить сообщение об ошибке.

add_extension(extension)

Добавляет расширение после создания среды.

Changelog

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

compile_expression(source, undefined_to_none=True)

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

Это полезно, если приложения хотят использовать те же правила, что и Jinja, в «конфигурационных файлах» шаблонов или аналогичных ситуациях.

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

>>> env = Environment()
>>> expr = env.compile_expression('foo == 42')
>>> expr(foo=23)
False
>>> expr(foo=42)
True

По умолчанию значение возврата преобразуется в None, если выражение возвращает неопределённое значение. Это можно изменить, установив undefined_to_none в False.

>>> env.compile_expression('var')() is None
True
>>> env.compile_expression('var', undefined_to_none=False)()
Undefined
Changelog

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

compile_templates(target, extensions=None, filter_func=None, zip='deflated', log_function=None, ignore_errors=True, py_compile=False)

Находит все шаблоны, которые может найти загрузчик, компилирует их и сохраняет в target. Если zip равно None, вместо zip-архива, шаблоны будут сохранены в каталоге. По умолчанию используется алгоритм сжатия deflate. Чтобы переключиться на другой алгоритм, zip можно установить в 'stored'.

extensions и filter_func передаются методу list_templates(). Каждый возвращённый шаблон будет скомпилирован в целевой каталог или zip-архив.

По умолчанию ошибки компиляции шаблонов игнорируются. Если предоставлена функция регистрации ошибок, ошибки регистрируются. Если вы хотите, чтобы ошибки синтаксиса шаблонов прерывали компиляцию, вы можете установить ignore_errors в False, и вы получите исключение при синтаксических ошибках.

Если py_compile установлено в True, вместо стандартных файлов .py будут созданы файлы .pyc. Этот флаг не выполняет никаких действий в pypy и Python 3, где файлы .pyc не выбираются автоматически и не приносят существенной пользы.

Changelog

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

extend(**attributes)

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

from_string(source, globals=None, template_class=None)

Загружает шаблон из строки. Парсит предоставленный исходный код и возвращает объект Template.

get_or_select_template(template_name_or_list, parent=None, globals=None)

Выполняет проверку типа и перенаправляет на select_template(), если передан итерируемый список имён шаблонов, в противном случае на get_template().

Changelog

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

get_template(name, parent=None, globals=None)

Загружает шаблон из загрузчика. Если настроен загрузчик, этот метод запрашивает у загрузчика шаблон и возвращает объект Template. Если параметр parent не None, вызывается join_path() для получения фактического имени шаблона перед загрузкой.

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

Если шаблон не найден, генерируется исключение TemplateNotFound.

Changelog

Изменено в версии 2.4: Если name — объект Template, он возвращается функцией без изменений.

join_path(template, parent)

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

Подклассы могут переопределять этот метод и реализовывать объединение путей шаблонов здесь.

list_templates(extensions=None, filter_func=None)

Возвращает список шаблонов для данной среды. Это требует, чтобы загрузчик поддерживал метод list_templates() загрузчика.

Если в папке шаблонов есть файлы помимо собственно шаблонов, возвращаемый список можно отфильтровать. Есть два способа: либо extensions установлен в список расширений файлов для шаблонов, либо предоставляется filter_func, который является вызываемым объектом, которому передаётся имя шаблона и который должен возвращать True, если шаблон должен быть включён в результирующий список.

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

Changelog

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

select_template(names, parent=None, globals=None)

Работает так же, как get_template(), но пытается найти несколько шаблонов, прежде чем завершиться неудачей. Если ни один из шаблонов не найден, генерируется исключение TemplatesNotFound.

Изменено в версии 2.11: Если names — Undefined, генерируется исключение UndefinedError. Если ни один шаблон не был найден, и names содержит Undefined, сообщение становится более информативным.

Changelog

Изменено в версии 2.4: Если names содержит объект Template, он возвращается функцией без изменений.

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

class jinja2.Template

Центральный объект шаблона. Этот класс представляет собой скомпилированный шаблон и используется для его вычисления.

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

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

Объекты шаблонов, созданные с помощью конструктора, а не среды, имеют атрибут environment, который указывает на временную среду, которая, вероятно, используется совместно другими шаблонами, созданными с помощью конструктора и совместимых настроек.

>>> template = Template('Hello {{ name }}!')
>>> template.render(name='John Doe') == u'Hello John Doe!'
True
>>> stream = template.stream(name='John Doe')
>>> next(stream) == u'Hello John Doe!'
True
>>> next(stream)
Traceback (most recent call last):
    ...
StopIteration
globals

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

name

Имя шаблона во время загрузки. Если шаблон был загружен из строки, это None.

filename

Имя файла шаблона в файловой системе, если он был загружен оттуда. В противном случае это None.

render([context])

Этот метод принимает те же аргументы, что и конструктор dict: словарь, подкласс словаря или некоторые ключевые аргументы. Если аргументы не заданы, контекст будет пустым. Эти два вызова делают одно и то же:

template.render(knights='that say nih')
template.render({'knights': 'that say nih'})

Этот метод возвращает отрендеренный шаблон в виде строки Unicode.

generate([context])

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

Он принимает те же аргументы, что и render().

stream([context])

Работает точно так же, как generate(), но возвращает TemplateStream.

render_async([context])

Работает аналогично render(), но возвращает корутину, которая, при ожидании, возвращает всю строку отрендеренного шаблона. Это требует включения асинхронной функции.

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

await template.render_async(knights='that say nih; asynchronously')
generate_async([context])

Асинхронная версия generate(). Работает очень похоже, но возвращает асинхронный итератор вместо этого.

make_module(vars=None, shared=False, locals=None)

Этот метод работает как атрибут module, когда вызывается без аргументов, но при каждом вызове будет пересчитывать шаблон вместо кеширования. Также можно передать словарь, который используется в качестве контекста. Аргументы аналогичны методу new_context().

property module

Шаблон как модуль. Используется для импортов в шаблоне во время выполнения, но также полезен, если нужно получить экспортированные переменные шаблона из слоя Python:

>>> t = Template('{% macro foo() %}42{% endmacro %}23')
>>> str(t.module)
'23'
>>> t.module.foo() == u'42'
True

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

class jinja2.environment.TemplateStream

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

Если буферизация включена с размером буфера 5, пять элементов объединяются в новую строку Unicode. Это особенно полезно, если вы отправляете большие шаблоны клиенту через WSGI, который сбрасывает буфер после каждой итерации.

disable_buffering()

Отключить буферизацию вывода.

dump(fp, encoding=None, errors='strict')

Вывести весь поток в файл или файлоподобный объект. По умолчанию записываются строки Unicode; если вы хотите закодировать перед записью, укажите encoding.

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

Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
enable_buffering(size=5)

Включить буферизацию. Буферизовать size элементов перед их выдачей.

Автоэскапирование

Изменения

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

Jinja2 теперь поддерживает автоэскапирование. Начиная с Jinja 2.9, расширение автоэскапирования удалено и интегрировано. Однако автоэскапирование по умолчанию пока не включено, хотя это, скорее всего, изменится в будущем. Рекомендуется настроить разумное значение по умолчанию для автоэскапирования. Это позволяет включать и отключать автоэскапирование для каждого шаблона (например, HTML или текст).

jinja2.select_autoescape(enabled_extensions=('html', 'htm', 'xml'), disabled_extensions=(), default_for_string=True, default=False)

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

Если вы хотите включить его для всех шаблонов, созданных из строк, или для всех шаблонов с расширениями .html и .xml:

from jinja2 import Environment, select_autoescape
env = Environment(autoescape=select_autoescape(
    enabled_extensions=('html', 'xml'),
    default_for_string=True,
))

Пример конфигурации для включения всегда, кроме случаев, когда шаблон оканчивается на .txt:

from jinja2 import Environment, select_autoescape
env = Environment(autoescape=select_autoescape(
    disabled_extensions=('txt',),
    default_for_string=True,
    default=True,
))

enabled_extensions — это итерируемый список всех расширений, для которых должно быть включено автоэскапирование. Аналогично, disabled_extensions — это список всех шаблонов, для которых оно должно быть отключено. Если шаблон загружен из строки, то используется значение по умолчанию из default_for_string. Если ничего не соответствует, начальное значение автоэскапирования устанавливается в значение default.

По соображениям безопасности эта функция работает без учета регистра.

Изменения

Добавлено в версии 2.9.

Вот рекомендуемая настройка, которая включает автоэскапирование для шаблонов, заканчивающихся на '.html', '.htm' и '.xml', и отключает его по умолчанию для всех остальных расширений. Для этого вы можете использовать функцию select_autoescape():

from jinja2 import Environment, select_autoescape
env = Environment(autoescape=select_autoescape(['html', 'htm', 'xml']),
                  loader=PackageLoader('mypackage'))

Функция select_autoescape() возвращает функцию, которая работает примерно так:

def autoescape(template_name):
    if template_name is None:
        return False
    if template_name.endswith(('.html', '.htm', '.xml'))

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

Внутри шаблонов поведение можно временно изменить, используя блок autoescape (см. Автоэскапирование Переопределения).

Примечания по именованию идентификаторов

Jinja2 использует обычные правила именования Python 2.x. Допустимые идентификаторы должны соответствовать [a-zA-Z_][a-zA-Z0-9_]*. На самом деле, в настоящее время не разрешены символы с кодами, отличными от ASCII. Это ограничение, скорее всего, исчезнет, как только идентификаторы Unicode будут полностью реализованы в Python 3.

Фильтры и тесты ищутся в отдельных именованных пространствах и имеют немного измененный синтаксис идентификаторов. Фильтры и тесты могут содержать точки для группировки фильтров и тестов по темам. Например, совершенно допустимо добавить функцию в словарь фильтров и вызвать её как to.unicode. Регулярное выражение для идентификаторов фильтров и тестов — [a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*`.

Типы неопределенных значений

Эти классы могут использоваться в качестве типов неопределенных значений. Конструктор Environment принимает параметр undefined, который может быть одним из этих классов или пользовательским подклассом Undefined. Всякий раз, когда движок шаблонов не может найти имя или получить доступ к атрибуту, создаётся один из этих объектов и возвращается. Некоторые операции с неопределёнными значениями разрешены, другие — нет.

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

```
class jinja2.Undefined

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

>>> foo = Undefined(name='foo')
>>> str(foo)
''
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
_undefined_hint

Либо None , либо строка Юникод с сообщением об ошибке для неопределённого объекта.

_undefined_obj

Либо None , либо владеющий объект, который вызвал создание неопределённого объекта (например, потому что атрибут не существует).

_undefined_name

Имя неопределённой переменной/атрибута или просто None , если такая информация отсутствует.

_undefined_exception

Исключение, которое должен генерировать неопределённый объект. Обычно это одно из UndefinedError или SecurityError.

_fail_with_undefined_error(*args, **kwargs)

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

class jinja2.DebugUndefined

Неопределённое значение, возвращающее отладочную информацию при выводе.

>>> foo = DebugUndefined(name='foo')
>>> str(foo)
'{{ foo }}'
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
class jinja2.StrictUndefined

Неопределённое значение, которое выдаёт предупреждение при выводе, итерации, проверках на истинность и различных сравнениях. Другими словами: с ним ничего нельзя сделать, кроме проверки на определённость с помощью теста defined.

>>> foo = StrictUndefined(name='foo')
>>> str(foo)
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
>>> not foo
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined

Также существует функция-фабрика, которая может декоратор неопределённых объектов для реализации ведения журнала при ошибках:

jinja2.make_logging_undefined(logger=None, base=None)

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

Пример:

logger = logging.getLogger(__name__)
LoggingUndefined = make_logging_undefined(
    logger=logger,
    base=Undefined
)
Changelog

Добавлено в версии 2.8.

Параметры
  • logger – используемый логгер. Если не указан, создаётся логгер по умолчанию.
  • base – базовый класс, к которому добавляется функциональность ведения журнала. По умолчанию это Undefined.

Неопределённые объекты создаются путём вызова undefined.

Реализация

Undefined объекты реализуются путём переопределения специальных __underscore__ методов. Например, по умолчанию класс Undefined реализует __unicode__ таким образом, что возвращает пустую строку, однако __int__ и другие всё ещё вызывают исключение. Чтобы разрешить преобразование в int, возвращая 0 , можно реализовать свой собственный:

class NullUndefined(Undefined):
    def __int__(self):
        return 0
    def __float__(self):
        return 0.0

Чтобы запретить метод, просто переопределите его и вызовите _undefined_exception. Поскольку это очень распространённый подход в неопределённых объектах, существует вспомогательный метод _fail_with_undefined_error(), который автоматически генерирует ошибку. Вот класс, который работает как обычный Undefined, но приводит к сбою при итерации:

class NonIterableUndefined(Undefined):
    __iter__ = Undefined._fail_with_undefined_error

Контекст

class jinja2.runtime.Context

Контекст шаблона содержит переменные шаблона. Он хранит значения, переданные в шаблон, а также имена, экспортируемые шаблоном. Создание экземпляров не поддерживается и бесполезно, так как он создаётся автоматически на различных этапах оценки шаблона и не должен создаваться вручную.

Контекст является неизменяемым. Изменения в parent не должны происходить, а изменения в vars разрешены только для сгенерированного кода шаблона. Фильтры шаблонов и глобальные функции, помеченные как contextfunction() , получают активный контекст в качестве первого аргумента и имеют право на доступ к контексту только для чтения.

Контекст шаблона поддерживает операции чтения словаря только для чтения (get, keys, values, items, iterkeys, itervalues, iteritems, __getitem__, __contains__). Кроме того, есть метод resolve(), который не выдает ошибку KeyError, а возвращает объект Undefined для отсутствующих переменных.

parent

Словарь неизменяемых глобальных переменных, которые шаблон ищет. Они могут исходить из другого Context, из Environment.globals или Template.globals , или указывают на словарь, созданный путём объединения глобальных переменных с переменными, переданными в функцию render. Его нельзя изменять.

vars

Локальные переменные шаблона. Этот список содержит функции окружения и контекста из области видимости parent, а также локальные изменения и экспортируемые переменные из шаблона. Шаблон будет изменять этот словарь во время оценки шаблона, но фильтрам и функциям контекста запрещено его изменять.

environment

Окружение, которое загрузило шаблон.

exported_vars

Этот набор содержит все имена, которые экспортирует шаблон. Значения для имён находятся в словаре vars. Для получения копии экспортируемых переменных как словаря можно использовать get_exported().

name

Имя загрузки шаблона, владеющего этим контекстом.

blocks

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

eval_ctx

Текущий Контекст оценки.

call(callable, *args, **kwargs)

Вызов вызываемого объекта с предоставленными аргументами и именованными аргументами, но вставка активного контекста или окружения в качестве первого аргумента, если вызываемый объект является contextfunction() или environmentfunction().

get_all()

Возвращает весь контекст в виде словаря, включая экспортируемые переменные. Из-за оптимизаций это может не быть фактической копией, поэтому будьте осторожны при её использовании.

get_exported()

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

resolve(key)

Ищет переменную, как __getitem__ или get , но возвращает объект Undefined с именем искомого имени.

Реализация

Контекст неизменяемый по той же причине, что и локальные переменные фреймов Python внутри функций неизменяемы. Как Jinja2, так и Python не используют контекст/локальные переменные фреймов как хранилище для переменных, а только как основной источник данных.

Когда шаблон обращается к переменной, не определённой в шаблоне, Jinja2 ищет переменную в контексте, после чего переменная обрабатывается как будто она была определена в шаблоне.

Загрузчики

Загрузчики отвечают за загрузку шаблонов из ресурса, например, файловой системы. Окружение будет сохранять скомпилированные модули в памяти, как и Python’s sys.modules. Однако, в отличие от sys.modules, этот кэш ограничен по размеру по умолчанию, и шаблоны автоматически перезагружаются. Все загрузчики являются подклассами BaseLoader. Если вы хотите создать свой собственный загрузчик, создайте подкласс BaseLoader и переопределите get_source.

class jinja2.BaseLoader

Базовый класс для всех лоадеров. Подклассируйте его и переопределите get_source для реализации собственного механизма загрузки. Окружение предоставляет метод get_template, который вызывает метод лоадера load для получения объекта Template.

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

from jinja2 import BaseLoader, TemplateNotFound
from os.path import join, exists, getmtime

class MyLoader(BaseLoader):

    def __init__(self, path):
        self.path = path

    def get_source(self, environment, template):
        path = join(self.path, template)
        if not exists(path):
            raise TemplateNotFound(template)
        mtime = getmtime(path)
        with file(path) as f:
            source = f.read().decode('utf-8')
        return source, path, lambda: mtime == getmtime(path)
get_source(environment, template)

Получить исходный код шаблона, имя файла и вспомогательную функцию перезагрузки шаблона. Ему передаются окружение и имя шаблона, и он должен вернуть кортеж в формате (source, filename, uptodate) или вызвать ошибку TemplateNotFound, если шаблон не найден.

Часть кортежа, отвечающая за исходный код, должна содержать исходный код шаблона в виде строки Unicode или байтовой строки ASCII. Имя файла должно содержать имя файла в файловой системе, если шаблон был загружен оттуда, в противном случае None. Имя файла используется Python для отладки, если не используется расширение лоадера.

Последний элемент кортежа — функция uptodate. Если включена автоматическая перезагрузка, она всегда вызывается для проверки изменений шаблона. Не передаются аргументы, поэтому функция должна где-то хранить предыдущее состояние (например, в замыкании). Если она возвращает False, шаблон будет перезагружен.

load(environment, name, globals=None)

Загружает шаблон. Этот метод ищет шаблон в кэше или загружает его, вызывая get_source(). Подклассы не должны переопределять этот метод, так как лоадеры, работающие с наборами других лоадеров (такие как PrefixLoader или ChoiceLoader), не будут вызывать этот метод, а вызовут get_source напрямую.

Вот список встроенных лоадеров, которые предоставляет Jinja2:

class jinja2.FileSystemLoader(searchpath, encoding='utf-8', followlinks=False)

Загружает шаблоны из файловой системы. Этот лоадер может находить шаблоны в папках файловой системы и является предпочтительным способом их загрузки.

Лоадер принимает путь к шаблонам в виде строки или, если нужны несколько мест, список из них, который затем просматривается в указанном порядке:

>>> loader = FileSystemLoader('/path/to/templates')
>>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])

По умолчанию кодировка шаблона — 'utf-8', которую можно изменить, установив параметр encoding на другое значение.

Для следования символическим ссылкам установите параметр followlinks в True:

>>> loader = FileSystemLoader('/path/to/templates', followlinks=True)
Изменения

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

class jinja2.PackageLoader(package_name, package_path='templates', encoding='utf-8')

Загружает шаблоны из каталога в пакете Python.

Параметры
  • package_name – Имя импорта пакета, содержащего каталог шаблонов.
  • package_path – Каталог внутри импортированного пакета, содержащий шаблоны.
  • encoding – Кодировка файлов шаблонов.

Следующий пример ищет шаблоны в каталоге pages внутри пакета project.ui.

loader = PackageLoader("project.ui", "pages")

Поддерживаются только пакеты, установленные как каталоги (стандартное поведение pip) или файлы zip/egg (менее распространённый случай). API Python для интроспекции данных в пакетах слишком ограничен, чтобы поддерживать другие методы установки так, как это требуется этому лоадеру.

Есть ограниченная поддержка PEP 420 пространств имён пакетов. Предполагается, что каталог шаблонов находится только в одном участнике пространства имён. Файлы zip, вносящие вклад в пространство имён, не поддерживаются.

Изменено в версии 2.11.0: Больше не использует setuptools в качестве зависимости.

Изменено в версии 2.11.0: Ограниченная поддержка PEP 420 пространств имён пакетов.

class jinja2.DictLoader(mapping)

Загружает шаблон из словаря Python. Ему передаётся словарь строк Unicode, связанных с именами шаблонов. Этот лоадер полезен для юнит-тестирования:

>>> loader = DictLoader({'index.html': 'source here'})

Так как автоматическая перезагрузка редко используется, она по умолчанию отключена.

class jinja2.FunctionLoader(load_func)

Лоадер, которому передаётся функция, выполняющая загрузку. Функция получает имя шаблона и должна вернуть строку Unicode с исходным кодом шаблона, кортеж в формате (source, filename, uptodatefunc) или None, если шаблон не существует.

>>> def load_template(name):
...     if name == 'index.html':
...         return '...'
...
>>> loader = FunctionLoader(load_template)

Функция uptodatefunc вызывается, если включена автоматическая перезагрузка, и должна вернуть True, если шаблон ещё актуален. Для получения дополнительной информации см. BaseLoader.get_source(), где есть то же возвращаемое значение.

class jinja2.PrefixLoader(mapping, delimiter='/')

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

loader = PrefixLoader({
    'app1':     PackageLoader('mypackage.app1'),
    'app2':     PackageLoader('mypackage.app2')
})

Загружая 'app1/index.html', загружается файл из пакета app1, загружая 'app2/index.html', загружается файл из второго.

class jinja2.ChoiceLoader(loaders)

Этот лоадер работает как PrefixLoader, только префикс не указан. Если шаблон не был найден одним лоадером, пробуется следующий.

>>> loader = ChoiceLoader([
...     FileSystemLoader('/path/to/user/templates'),
...     FileSystemLoader('/path/to/system/templates')
... ])

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

class jinja2.ModuleLoader(path)

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

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

>>> loader = ChoiceLoader([
...     ModuleLoader('/path/to/compiled/templates'),
...     FileSystemLoader('/path/to/templates')
... ])

Шаблоны можно предварительно скомпилировать с помощью Environment.compile_templates().

Кэш байткода

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

Это особенно полезно, если у вас веб-приложение, которое инициализируется при первом запросе, и Jinja компилирует множество шаблонов сразу, что замедляет приложение.

Чтобы использовать кэш байткода, создайте его и передайте его в Environment.

class jinja2.BytecodeCache

Чтобы реализовать свой собственный кэш байткода, нужно подклассировать этот класс и переопределить load_bytecode() и dump_bytecode(). Оба этих метода получают Bucket.

Очень простой кэш байткода, который сохраняет байткод на файловой системе:

from os import path

class MyCache(BytecodeCache):

    def __init__(self, directory):
        self.directory = directory

    def load_bytecode(self, bucket):
        filename = path.join(self.directory, bucket.key)
        if path.exists(filename):
            with open(filename, 'rb') as f:
                bucket.load_bytecode(f)

    def dump_bytecode(self, bucket):
        filename = path.join(self.directory, bucket.key)
        with open(filename, 'wb') as f:
            bucket.write_bytecode(f)

Более продвинутая версия кэша байткода на основе файловой системы входит в Jinja.

clear()

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

dump_bytecode(bucket)

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

load_bytecode(bucket)

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

class jinja2.bccache.Bucket(environment, key, checksum)

Ведра используются для хранения байткода одного шаблона. Он создаётся и инициализируется кэшем байткода и передаётся функциям загрузки.

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

environment

Окружение, которое создало ведро.

key

Уникальный ключ кэша для этого ведра

code

Байткод, если он загружен, в противном случае None.

bytecode_from_string(string)

Загрузить байткод из строки.

bytecode_to_string()

Возвращает байткод в виде строки.

load_bytecode(f)

Загружает байткод из файла или объекта, подобного файлу.

reset()

Сбрасывает ведро (разгружает байткод).

write_bytecode(f)

Выгружает байткод в файл или объект, подобный файлу.

Встроенные кэши байткода:

class jinja2.FileSystemBytecodeCache(directory=None, pattern='__jinja2_%s.cache')

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

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

Шаблон может использоваться для работы с несколькими отдельными кэшами в одном каталоге. По умолчанию используется шаблон '__jinja2_%s.cache'. %s заменяется на ключ кэша.

>>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')

Этот кэш байткода поддерживает очистку кэша с помощью метода clear.

class jinja2.MemcachedBytecodeCache(client, prefix='jinja2/bytecode/', timeout=None, ignore_memcache_errors=True)

Этот класс реализует кэш байткода, использующий кэш memcache для хранения информации. Он не навязывает конкретную библиотеку memcache (memcache из tummy или cmemcache), но примет любой класс, предоставляющий необходимый минимальный интерфейс.

Библиотеки, совместимые с этим классом:

  • cachelib
  • python-memcached

(К сожалению, интерфейс кэша Django несовместим, потому что он не поддерживает хранение двоичных данных, только unicode. Однако вы можете передать базовый клиент кэша в кэш байткода, доступный как django.core.cache.cache._client.)

Минимальный интерфейс для клиента, передаваемого в конструктор, выглядит так:

class MinimalClientInterface
set(key, value[, timeout])

Сохраняет байткод в кэше. value — строка, а timeout — срок действия ключа. Если срок действия не указан, предполагается значение по умолчанию или отсутствие срока действия; если указан, это целое число, обозначающее количество секунд, в течение которого элемент кэша должен существовать.

get(key)

Возвращает значение для ключа кэша. Если элемент не существует в кэше, возвращается значение None.

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

Этот кэш байткода не поддерживает очистку используемых элементов кэша. Метод clear является функцией бездействия.

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

Новое в версии 2.7: Добавлена поддержка игнорирования ошибок memcache через параметр ignore_memcache_errors.

Асинхронная поддержка

Начиная с версии 2.9, Jinja2 также поддерживает конструкции Python async и await. Что касается разработчиков шаблонов, эта функция полностью скрыта от них, однако разработчик должен знать о её реализации, так как она влияет на типы API, которые можно безопасно экспонировать в среде шаблонов.

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

  • для обработки шаблонов потребуется цикл событий для текущей нити (asyncio.get_event_loop должен вернуть один)
  • весь код генерации шаблонов внутренне использует асинхронные генераторы, что означает, что вы будете платить за производительность даже если используются не синхронные методы!
  • синхронные методы основаны на асинхронных методах, если включен асинхронный режим, что означает, что render , например, внутренне вызовет render_async и выполнит его в рамках текущего цикла событий до завершения выполнения.

Из функций в шаблонах можно возвращать асинхронные объекты, и любой вызов функции в шаблоне автоматически ожидает результат. Это означает, что вы можете предоставить метод, который асинхронно загружает данные из базы данных, если это необходимо, и с точки зрения разработчика шаблонов это просто функция, которую они могут вызвать. Это означает, что await , который вы обычно используете в Python, подразумевается. Однако это относится только к вызовам функций. Если, например, атрибут будет асинхронным объектом, это не приведёт к ожидаемому поведению.

Аналогично, циклы итерации с for поддерживают асинхронные итераторы.

Политики

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

Пример:

env.policies['urlize.rel'] = 'nofollow noopener'
compiler.ascii_str:

Этот булево значение контролирует, будет ли Jinja2 хранить только символы ASCII в виде строковых литералов байтов вместо строковых литералов Unicode в Python 2. Это значение всегда было включено для версий Jinja ниже 2.9, а теперь может быть изменено. Раньше это делалось так, потому что некоторые API в Python 2 плохо работали со строками Unicode (например, API datetime strftime). Однако сейчас иногда верно обратное (например, str.format). Если это значение установлено в False, все строки хранятся как Unicode во внутренней форме.

truncate.leeway:

Настраивает значение по умолчанию для фильтра truncate. Леeway был добавлен в 2.9, но для восстановления совместимости со старыми шаблонами его можно настроить на 0, чтобы получить старое поведение. По умолчанию 5.

urlize.rel:

Строка, определяющая элементы атрибута rel сгенерированных ссылок с помощью фильтра urlize. Эти элементы всегда добавляются. По умолчанию noopener.

urlize.target:

По умолчанию целевой адрес, который используется для ссылок из фильтра urlize , если другой адрес не определён явно.

json.dumps_function:

Если это значение установлено на значение отличное от None, фильтр tojson будет вызывать эту функцию вместо стандартной. Обратите внимание, что эта функция должна принимать произвольные дополнительные аргументы, которые могут быть переданы в будущем фильтром. В настоящее время единственный аргумент, который может быть передан, это indent. По умолчанию используется функция вывода json.dumps.

json.dumps_kwargs:

Ключевые слова, которые будут переданы функции вывода. По умолчанию {'sort_keys': True}.

Утилиты

Эти вспомогательные функции и классы полезны, если вы добавляете пользовательские фильтры или функции в среду Jinja2.

jinja2.environmentfilter(f)

Декоратор для маркировки фильтров, зависящих от среды. Текущая Environment передаётся фильтру в качестве первого аргумента.

jinja2.contextfilter(f)

Декоратор для маркировки фильтров, зависящих от контекста. Текущий Context будет передан в качестве первого аргумента.

jinja2.evalcontextfilter(f)

Декоратор для маркировки фильтров, зависящих от контекста вычисления. Объект контекста вычисления передаётся в качестве первого аргумента. Дополнительную информацию о контексте вычисления см. в разделе Контекст вычисления.

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

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

jinja2.environmentfunction(f)

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

jinja2.contextfunction(f)

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

@contextfunction
def get_exported_names(context):
    return sorted(context.exported_vars)
jinja2.evalcontextfunction(f)

Этот декоратор можно использовать для маркировки функции или метода как вызываемого из контекста вычисления. Это аналогично contextfunction(), но вместо передачи контекста передаётся объект контекста вычисления. Дополнительную информацию о контексте вычисления см. в разделе Контекст вычисления.

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

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

jinja2.escape(s)

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

Возвращаемое значение — строка Markup.

jinja2.clear_caches()

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

jinja2.is_undefined(obj)

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

def default(var, default=''):
    if is_undefined(var):
        return default
    return var
class jinja2.Markup([string])

Строка, готовая для безопасной вставки в документ HTML или XML, либо потому что она была экранирована, либо потому что она была помечена как безопасная.

Передача объекта в конструктор преобразует его в текст и оборачивает его, чтобы пометить его как безопасный без экранирования. Для экранирования текста используйте метод класса escape() вместо этого.

>>> Markup('Hello, <em>World</em>!')
Markup('Hello, <em>World</em>!')
>>> Markup(42)
Markup('42')
>>> Markup.escape('Hello, <em>World</em>!')
Markup('Hello &lt;em&gt;World&lt;/em&gt;!')

Этот класс реализует интерфейс __html__(), используемый некоторыми фреймворками. Передача объекта, реализующего __html__(), обернёт вывод этого метода, пометив его как безопасный.

>>> class Foo:
...     def __html__(self):
...         return '<a href="/foo">foo</a>'
...
>>> Markup(Foo())
Markup('<a href="/foo">foo</a>')

Это подкласс типа text (str в Python 3, unicode в Python 2). Он имеет те же методы, что и этот тип, но все методы экранируют свои аргументы и возвращают экземпляр Markup.

>>> Markup('<em>%s</em>') % 'foo & bar'
Markup('<em>foo &amp; bar</em>')
>>> Markup('<em>Hello</em> ') + '<foo>'
Markup('<em>Hello</em> &lt;foo&gt;')
classmethod escape(s)

Экранирование строки. Вызывает escape() и гарантирует, что для подклассов возвращается правильный тип.

striptags()

Разбирает разметку, удаляет теги и нормализует пробелы до одного пробела.

>>> Markup('Main &raquo;        <em>About</em>').striptags()
'Main » About'
unescape()

Преобразует экранированную разметку обратно в строку текста. Это заменяет HTML-сущности соответствующими символами.

>>> Markup('Main &raquo; <em>About</em>').unescape()
'Main » <em>About</em>'

Примечание

Класс Jinja2 Markup совместим как минимум с Pylons и Genshi. Ожидается, что вскоре больше шаблонизаторов и фреймворков подхватят концепцию __html__.

Исключения

exception jinja2.TemplateError(message=None)

Базовый класс для всех ошибок шаблонов.

exception jinja2.UndefinedError(message=None)

Вызывается, если шаблон пытается выполнить операцию над Undefined.

exception jinja2.TemplateNotFound(name, message=None)

Вызывается, если шаблон не существует.

Изменено в версии 2.11: Если заданное имя равно Undefined и сообщение не было предоставлено, выбрасывается UndefinedError.

exception jinja2.TemplatesNotFound(names=(), message=None)

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

Изменено в версии 2.11: Если имя в списке имён равно Undefined, отображается сообщение об этом неопределённом значении вместо пустой строки.

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

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

exception jinja2.TemplateSyntaxError(message, lineno, name=None, filename=None)

Вызывается, чтобы сообщить пользователю о проблеме с шаблоном.

message

Сообщение об ошибке в виде байтовой строки utf-8.

lineno

Номер строки, где произошла ошибка

name

Имя загрузки шаблона в виде строки unicode.

filename

Имя файла, загрузившего шаблон в виде байтовой строки в кодировке файловой системы (вероятно, utf-8 или mbcs в системах Windows).

Причина, по которой имя файла и сообщение об ошибке являются байтовыми строками, а не строками unicode, заключается в том, что Python 2.x не использует unicode для исключений и отладочной информации, а также для компилятора. Это изменится в Python 3.

exception jinja2.TemplateAssertionError(message, lineno, name=None, filename=None)

Как ошибка синтаксиса шаблона, но охватывает случаи, когда что-то в шаблоне вызвало ошибку во время компиляции, которая не обязательно была вызвана ошибкой синтаксиса. Однако это непосредственный подкласс TemplateSyntaxError и имеет те же атрибуты.

Пользовательские фильтры

Пользовательские фильтры — это обычные функции Python, которые принимают левую часть фильтра в качестве первого аргумента и аргументы, переданные фильтру, в качестве дополнительных аргументов или ключевых аргументов.

Например, в фильтре {{ 42|myfilter(23) }} функция вызывалась бы с myfilter(42, 23). Здесь, например, простой фильтр, который можно применять к объектам datetime для их форматирования:

def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
    return value.strftime(format)

Его можно зарегистрировать в среде шаблона, обновив словарь filters в среде:

environment.filters['datetimeformat'] = datetimeformat

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

written on: {{ article.pub_date|datetimeformat }}
publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}

Фильтры также могут получать текущий контекст шаблона или среду. Это полезно, если фильтр хочет вернуть неопределённое значение или проверить текущее autoescape значение. Для этого существуют три декоратора: environmentfilter(), contextfilter() и evalcontextfilter().

Вот небольшой пример фильтра, который разбивает текст на HTML-неразрывные пробелы и абзацы и помечает возвращаемое значение как безопасную HTML-строку, если включено автоматическое экранирование:

import re
from jinja2 import evalcontextfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', Markup('<br>\n'))
                          for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

Фильтры контекста работают так же, только первый аргумент — это текущий активный Context вместо среды.

Контекст вычисления

Контекст вычисления (коротко — контекст вычисления или ctx вычисления) — это новый объект, представленный в Jinja 2.4, который позволяет активировать и деактивировать скомпилированные функции во время выполнения.

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

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

Предыдущие версии:

@environmentfilter
def filter(env, value):
    result = do_something(value)
    if env.autoescape:
        result = Markup(result)
    return result

В новых версиях вы можете использовать contextfilter() и получить доступ к контексту вычисления из фактического контекста или использовать evalcontextfilter(), который напрямую передаёт контекст вычисления функции:

@contextfilter
def filter(context, value):
    result = do_something(value)
    if context.eval_ctx.autoescape:
        result = Markup(result)
    return result

@evalcontextfilter
def filter(eval_ctx, value):
    result = do_something(value)
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

Контекст вычисления не должен изменяться во время выполнения. Изменения должны происходить только с помощью nodes.EvalContextModifier и nodes.ScopedEvalContextModifier из расширения, а не непосредственно на объекте контекста вычисления.

class jinja2.nodes.EvalContext(environment, template_name=None)

Содержит информацию о времени вычисления. К нему можно добавлять пользовательские атрибуты в расширениях.

autoescape

True или False в зависимости от того, включено ли автоэкранирование.

volatile

True если компилятор не может оценить некоторые выражения во время компиляции. Во время выполнения это всегда должно быть False.

Пользовательские тесты

Тесты работают как фильтры, только тест не может получить доступ к среде или контексту и не может быть сколь угодно многократно применён. Возвращаемое значение теста должно быть True или False . Цель теста — предоставить разработчикам шаблонов возможность выполнять проверки типа и соответствия.

Вот простой тест, который проверяет, является ли переменная простым числом:

import math

def is_prime(n):
    if n == 2:
        return True
    for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
        if n % i == 0:
            return False
    return True

Его можно зарегистрировать в среде шаблона, обновив словарь tests в среде:

environment.tests['prime'] = is_prime

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

{% if 42 is prime %}
    42 is a prime number
{% else %}
    42 is not a prime number
{% endif %}

Глобальное пространство имён

Переменные, хранящиеся в словаре Environment.globals, являются специальными, поскольку они доступны и для импортированных шаблонов, даже если они импортированы без контекста. Здесь вы можете разместить переменные и функции, которые должны быть доступны всегда. Дополнительно существует Template.globals, представляющие собой переменные, доступные для конкретного шаблона и доступные для всех вызовов render().

API Низкого Уровня

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

Environment.lex(source, name=None, filename=None)

Разбирает заданный исходный код и возвращает генератор, который возвращает токены как кортежи в формате (lineno, token_type, value). Это может быть полезно для разработки расширений и отладки шаблонов.

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

Environment.parse(source, name=None, filename=None)

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

Если вы разрабатываете расширения Jinja, это даст вам хороший обзор дерева узлов, сгенерированного.

Environment.preprocess(source, name=None, filename=None)

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

Template.new_context(vars=None, shared=False, locals=None)

Создает новый Context для этого шаблона. Предоставленные переменные будут переданы в шаблон. По умолчанию глобальные переменные добавляются в контекст. Если shared установлено в True, данные передаются в контекст как есть без добавления глобальных переменных.

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

Template.root_render_func(context)

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

Если в коде шаблона произойдет исключение, движок шаблонов не перепишет исключение, а передаст исходное. Фактически, эта функция должна вызываться только изнутри вызова render() / generate() / stream().

Template.blocks

Словарь функций рендеринга блоков. Каждая из этих функций работает точно так же, как root_render_func() с теми же ограничениями.

Template.is_up_to_date

Это атрибут False, если доступна более новая версия шаблона, в противном случае True.

Примечание

API низкого уровня хрупкий. Будущие версии Jinja2 постараются не изменять его несовместимым обратным образом, но изменения в ядре Jinja2 могут проявиться. Например, если Jinja2 добавит новый узел AST в более поздних версиях, который может возвращать parse().

API Метаданных

Изменения

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

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

jinja2.meta.find_undeclared_variables(ast)

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

>>> from jinja2 import Environment, meta
>>> env = Environment()
>>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
>>> meta.find_undeclared_variables(ast) == set(['bar'])
True

Реализация

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

jinja2.meta.find_referenced_templates(ast)

Ищет все ссылаемые шаблоны в дереве AST. Это вернёт итератор по всем жёстко заданным расширениям, включениям и импортам шаблонов. Если используется динамическое наследование или включение, None будет возвращено.

>>> from jinja2 import Environment, meta
>>> env = Environment()
>>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
>>> list(meta.find_referenced_templates(ast))
['layout.html', None]

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

© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/2.9.x/api/

Spec-Zone.ru

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