Шаблоны
Flask использует Jinja2 в качестве движка шаблонов. Вы, очевидно, можете использовать другой движок шаблонов, но вам по-прежнему необходимо установить Jinja2 для запуска самого Flask. Это требование необходимо для активации расширенных возможностей. Расширение может зависеть от наличия Jinja2.
Этот раздел предоставляет лишь краткое введение в то, как Jinja2 интегрируется в Flask. Если вам нужна информация о синтаксисе самого движка шаблонов, перейдите к официальной документации Jinja2 Template Documentation для получения более подробной информации.
Настройка Jinja
Если не настраивать иначе, Jinja2 настраивается Flask следующим образом:
- автовывод HTML-сущностей включён для всех шаблонов, заканчивающихся на
.html,.htm,.xmlи.xhtml, когда используетсяrender_template(). - автовывод HTML-сущностей включён для всех строк при использовании
render_template_string(). - шаблон может включить/отключить автовывод HTML-сущностей с помощью тега
{% autoescape %}. - Flask добавляет несколько глобальных функций и вспомогательных функций в контекст Jinja2, помимо значений, присутствующих по умолчанию.
Стандартный контекст
По умолчанию в шаблонах Jinja2 доступны следующие глобальные переменные:
- config
-
Текущий объект конфигурации (
flask.Flask.config)Изменения
Изменено в версии 0.10: Теперь всегда доступен, даже в импортированных шаблонах.
Добавлен в версии 0.6.
- request
-
Текущий объект запроса (
flask.request). Эта переменная недоступна, если шаблон был отображён без активного контекста запроса.
- session
-
Текущий объект сессии (
flask.session). Эта переменная недоступна, если шаблон был отображён без активного контекста запроса.
- g
-
Связанный с запросом объект для глобальных переменных (
flask.g). Эта переменная недоступна, если шаблон был отображён без активного контекста запроса.
- url_for()
-
Функция
flask.url_for().
- get_flashed_messages()
-
Функция
flask.get_flashed_messages().
Поведение контекста Jinja
Эти переменные добавляются в контекст переменных, они не являются глобальными переменными. Разница заключается в том, что по умолчанию они не будут отображаться в контексте импортированных шаблонов. Это частично вызвано соображениями производительности, частично для ясности.
Что это значит для вас? Если у вас есть макрос, который вы хотите импортировать и который должен получить доступ к объекту запроса, у вас есть два варианта:
- Вы явно передаёте запрос макросу в качестве параметра или атрибут объекта запроса, который вас интересует.
- Вы импортируете макрос «с контекстом».
Импорт с контекстом выглядит так:
{% from '_helpers.html' import my_macro with context %}
Управление автовыводом HTML-сущностей
Автовывод HTML-сущностей — это концепция автоматического преобразования специальных символов в HTML-сущности. Специальные символы в смысле HTML (или XML, и, следовательно, XHTML) — &, >, <, " и '. Поскольку эти символы имеют определённое значение в документах, вы должны заменить их так называемыми «сущностями», если хотите использовать их в тексте. Не делать этого не только приведёт к неудобствам для пользователя из-за невозможности использовать эти символы в тексте, но также может привести к проблемам безопасности. (см. Межсайтовая атака на скрипты (XSS))
Иногда, однако, вам может потребоваться отключить автовывод HTML-сущностей в шаблонах. Это может быть необходимо, если вы хотите явно вставить HTML в страницы, например, если они получены из системы, генерирующей безопасный HTML, как конвертер Markdown в HTML.
Есть три способа сделать это:
- В коде Python оберните строку HTML объектом
Markupперед передачей его шаблону. Это, как правило, рекомендуемый способ. - Внутри шаблона используйте фильтр
|safeдля явного обозначения строки как безопасного HTML ({{ myvariable|safe }}) - Временное отключение системы автовывода HTML-сущностей.
Чтобы отключить систему автовывода HTML-сущностей в шаблонах, вы можете использовать блок {%
autoescape %}:
{% autoescape false %}
<p>autoescaping is disabled here
<p>{{ will_not_be_escaped }}
{% endautoescape %}
Внимательно относитесь к переменным, которые вы используете в этом блоке.
Регистрация фильтров
Если вы хотите зарегистрировать собственные фильтры в 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 %}
Обработчики контекста
Для автоматической инъекции новых переменных в контекст шаблона в Flask существуют обработчики контекста. Обработчики контекста выполняются перед рендерингом шаблона и могут вводить новые значения в контекст шаблона. Обработчик контекста — это функция, которая возвращает словарь. Ключи и значения этого словаря затем объединяются с контекстом шаблона для всех шаблонов приложения:
@app.context_processor
def inject_user():
return dict(user=g.user)
Обработчик контекста выше делает переменную user доступной в шаблоне со значением g.user. Этот пример не очень интересен, потому что g доступен в шаблонах, но он показывает, как это работает.
Переменные не ограничиваются значениями; обработчик контекста также может сделать доступными функции для шаблонов (поскольку Python позволяет передавать функции):
@app.context_processor
def utility_processor():
def format_price(amount, currency="€"):
return f"{amount:.2f}{currency}"
return dict(format_price=format_price)
Обработчик контекста выше делает функцию format_price доступной для всех шаблонов:
{{ format_price(0.33) }}
Вы также могли бы реализовать format_price как фильтр шаблона (см. Регистрация фильтров), но это демонстрирует, как передавать функции в обработчике контекста.
Потоковая передача данных
Иногда полезно не отображать весь шаблон как одну полную строку, а отображать его как поток, возвращая более мелкие наращиваемые строки. Это может использоваться для потоковой передачи HTML частями для ускорения начальной загрузки страницы или для экономии памяти при рендеринге очень больших шаблонов.
Движок шаблонов Jinja2 поддерживает рендеринг шаблона частями, возвращая итератор строк. Flask предоставляет функции stream_template() и stream_template_string(), чтобы сделать это проще в использовании.
from flask import stream_template
@app.get("/timeline")
def timeline():
return stream_template("timeline.html")
Эти функции автоматически применяют обёртку stream_with_context(), если запрос активен, так что он остаётся доступным в шаблоне.
© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.2.x/templating/