Шаблоны
Flask использует Jinja2 в качестве движка шаблонов. Вы, очевидно, можете использовать другой движок шаблонов, но вам все равно необходимо установить Jinja2, чтобы запустить сам Flask. Это требование необходимо для включения расширенных возможностей. Расширение может зависеть от наличия Jinja2.
Этот раздел предоставляет только очень краткое введение в то, как Jinja2 интегрируется в Flask. Если вы хотите получить информацию о синтаксисе самого движка шаблонов, перейдите к официальной документации по шаблонам Jinja2 для получения дополнительной информации.
Настройка Jinja
Если не настраивать, Jinja2 настраивается Flask следующим образом:
- автовывод кода включен для всех шаблонов, заканчивающихся на
.html,.htm,.xml,.xhtml, а также.svgпри использованииrender_template(). - автовывод кода включен для всех строк при использовании
render_template_string(). - шаблон может включить/отключить автовывод кода с помощью тега
{% 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 (или XML, и, следовательно, XHTML) — это &, >, <, " и '. Поскольку эти символы имеют определенные значения в документах сами по себе, их необходимо заменять так называемыми «сущностями», если вы хотите использовать их для текста. Не делая этого, вы не только вызовете неудовлетворенность пользователя из-за невозможности использования этих символов в тексте, но также можете столкнуться с проблемами безопасности. (см. Межсайтовый скриптинг (XSS))
Иногда, однако, вам потребуется отключить автовывод кода в шаблонах. Это может быть необходимо, если вы хотите явно вставить HTML в страницы, например, если они поступают из системы, которая генерирует безопасный HTML, как преобразователь Markdown в HTML.
Существует три способа достижения этого:
- В коде Python оберните строку HTML в объект
Markupперед передачей ее в шаблон. Это, как правило, рекомендуемый способ. - Внутри шаблона используйте фильтр
|safeдля явного обозначения строки как безопасного HTML ({{ myvariable|safe }}) - Временно отключите систему автовывода кода.
Чтобы отключить систему автовывода кода в шаблонах, можно использовать блок {%
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.3.x/templating/