#6 Шаблоны во Flask

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

Шаблоны

Шаблон — это всего лишь текстовый файл с HTML-кодом и дополнительными элементами разметки, которые обозначают динамический контент. Последний станет известен в момент запроса. Процесс, во время которого динамическая разметка заменяется, и генерируется статическая HTML-страница, называется отрисовкой (или рендерингом) шаблона. Во Flask есть встроенный движок шаблонов Jinja, который и занимается тем, что конвертирует шаблон в статический HTML-файл.

Jinja — один из самых мощных и популярных движков для обработки шаблонов для языка Python. Он должен быть известен пользователям Django. Но стоит понимать, что Flask и Jinja – два разных пакета, и они могут использоваться отдельно.

Отрисовка шаблонов с помощью render_template()

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

Этот код меняет расположение шаблонов по умолчанию на папку jinja_templates внутри папки приложения.

app = Flask(__name__, template_folder="jinja_templates")

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

Создаем новую папку templates внутри папки приложения flask_app. В templates — файл index.html со следующим кодом:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

  <p>Name: {{ name }}</p>

</body>
</html>

Стоит обратить внимание, что в «базовом» HTML-шаблоне есть динамический компонент {{ name }}. Переменная name внутри фигурных скобок представляет собой переменную, значение которой будет определено во время отрисовки шаблона. В качестве примера можно написать, что значением name будет Jerry. Тогда после рендеринга шаблона выйдет следующий код.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

  <p>Name: Jerry</p>

</body>
</html>

Flask предоставляет функцию rended_template для отрисовки шаблонов. Она интегрирует Jinja во Flask. Чтобы отрисовать шаблон, нужно вызвать rended_template() с именем шаблона и данными, которые должны быть в шаблоне в виде аргументов-ключевых слов. Аргументы-ключевые слова, которые передаются шаблонам, известны как контекст шаблона. Следующий код показывает, как отрисовать шаблон index.html с помощью render_template().

from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html', name='Jerry')
#...

Важно обратить внимание, что name в name='Jerry' ссылается на переменную, упомянутую в шаблоне index.html.

Если сейчас зайти на https://localhost:5000/, выйдет следующий ответ:

Отрисовка шаблонов с помощью render_template()

Если render_template() нужно передать много аргументов, можно не разделять их запятыми (,), а создать словарь и использовать оператор **, чтобы передать аргументы-ключевые слова функции. Например:

@app.route('/')
def index():
    name, age, profession = "Jerry", 24, 'Programmer'
    template_context = dict(name=name, age=age, profession=profession)
    return render_template('index.html', **template_context)

Шаблон index.html теперь имеет доступ к трем переменным шаблона: name, age и profession.

Что случится, если не определить контекст шаблона?

Ничего не случится, не будет ни предупреждений, ни исключений. Jinja отрисует шаблон как обычно, а на местах пропусков использует пустые строки. Чтобы увидеть это поведение, необходимо изменить функцию представления index() следующим образом:

#...
@app.route('/')
def index():
    return render_template('index.html')
#...

Теперь при открытии https://localhost:5000/ выйдет следующий ответ:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

  <p>Name: </p>

</body>
</html>

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

Отрисовка шаблонов в консоли

Для тестирования рендерить шаблоны можно и в консоли. Это просто и не требует создания нескольких файлов. Для начала нужно запустить Python и импортировать класс Template из пакета jinja2 следующим образом.

>>>  from jinja2 import Template

Для создания объекта Templates нужно передать содержимое шаблона в виде строки.

>>>  t = Template("Name: {{ name }}")

Чтобы отрендерить шаблон, нужно вызвать метод render() объекта Template вместе с данными аргументами-ключевыми словами

>>> t.render(name='Jerry')
'Name: Jerry'

В следующем уроке речь пойдет о шаблонизаторе Jinja.