Армин Роначер. Шаблоны Jinja2 во Flask, 2012

Перевод статьи: Templates

Автор: Армин Роначер (Armin Ronacher)

Flask использует в качестве системы шаблонизации Jinja2. Можно использовать другие системы шаблонизации, но для запуска Flask всё равно необходимо установить Jinja2. Это необходимо для использования дополнительных возможностей. Расширения могут зависеть от наличия Jinja2.

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

1. Установка Jinja

По умолчанию Flask настраивает Jinja2 следующим образом:

2. Стандартный контекст

По умолчанию из шаблонов Jinja2 доступны следующие глобальные переменные:

Переменная Описание
config

Объект текущей конфигурации (flask.config)

Новинка версии 0.6.

request Объект текущего запроса (flask.request)
session Объект текущего сеанса (flask.session)
g Связанный с запросом объект с глобальными переменными (flask.g)
url_for() Функция flask.url_for()
get_flashed_messages() Функция flask.get_flashed_messages()

3. Контекстное поведение Jinja

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

Какое это имеет значение? Если вам нужно получить доступ из макроса к объекту запроса, есть две возможности:

  1. явным образом передать объект запроса или его атрибут в макрос в качестве параметра.
  2. импортировать макрос с контекстом, указав ключевые слова "with context".

Импорт с контекстом выглядит следующим образом:

{% from '_helpers.html' import my_macro with context %}

4. Стандартные фильтры

В дополнение к собственным фильтрам Jinja2, доступны следующие фильтры:

tojson()

Эта функция конвертирует переданный объект в JSON-представление. Это может быть полезно, когда нужно на лету сгенерировать JavaScript.

Отметим, что внутри тегов script не должно производиться экранирование, поэтому убедитесь в том, что отключили экранирование при помощи фильтра |safe, если собираетесь использовать фильтр tojson внутри тегов script:

<script type=text/javascript>
  doSomethingWith({{ user.username|tojson|safe }});
</script>

Фильтр |tojson правильно экранирует прямую косую черту.

5. Управление автоэкранированием

Автоэкранирование - это автоматическое экранирование специальных символов. Специальными символами в HTML (а также в XML и в XHTML) являются &, >, <, " и '. Поскольку эти символы имеют особое значение в документах, для использования в тексте их нужно заменить на так называемые "сущности". Если этого не сделать, это не только может повлиять на невозможность использования этих символов пользователем, но и привести к проблемам с безопасностью (см. Кросс-сайтовый скриптинг - XSS).

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

Для достижения этого есть три способа:

Для отключения системы автоэкранирования в шаблонах можно воспользоваться блоком {% autoescape %}:

{% autoescape false %}
  <p>здесь автоэкранирование отключено
  <p>{{ will_not_be_escaped }}
{% endautoescape %}

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

6. Регистрация фильтров

Если нужно зарегистрировать собственные фильтры в Jinja2, у есть два способа. Можно просто поместить их вручную в атрибут jinja_env приложения или использовать декоратор template_filter().

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

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

def reverse_filter(s):
    return s[::-1]

app.jinja_env.filters['reverse'] = reverse_filter

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

{% for x in mylist | reverse %}
{% endfor %}

7. Процессоры контекста

Для автоматической вставки в контекст шаблона новых переменных существуют процессоры контекста Flask. Процессоры контекста запускаются перед отрисовкой шаблона и позволяют добавить новые переменные в контекст. Процессор контекста - это функция, возвращающая словарь, который будет объединён с контекстом шаблона, для всех шаблонов в приложении. Например, для app:

@app.context_processor
def inject_user():
    return dict(user=g.user)

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

Процессор контекста может передавать в шаблон не только переменные, но и функции (поскольку Python позволяет передавать функции):

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}.format(amount, currency)
    return dict(format_price=format_price)

Вышеприведённый процессор контекста передаст функцию format_price во все шаблоны:

{{ format_price(0.33) }}

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

8. Примечания переводчика

Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.

Написать автору перевода