Рендеринг шаблона и вывод переменных в HTML-шаблон
Функция render()
не только связывает view-функцию и шаблон, но и позволяет передать в этот шаблон данные, сгенерированные во view-функции. Данные, предназначенные для вывода на страницу, упаковывают в словарь и передают в функцию render()
в качестве третьего, необязательного аргумента. Ключи словаря в специальных тегах подставляют в шаблон — и при рендеринге вместо этих ключей будут выведены значения, связанные с этими ключами.Рендеринг (англ. rendering, «визуализация») — это превращение исходного кода в результат, который видит пользователь. Например, 3D-мультипликаторы в программах трёхмерной графики создают персонажей и эффекты, а потом, после рендеринга исходных файлов, получается видео.
def index(request):
# Адрес шаблона сохраним в переменную, это не обязательно, но удобно
template = 'ice_cream/index.html'
# Строку, которую надо вывести на страницу, тоже сохраним в переменную
title = 'Анфиса для друзей'
# Словарь с данными принято называть context
context = {
# В словарь можно передать переменную
'title': title,
# А можно сразу записать значение в словарь. Но обычно так не делают
'text': 'Главная страница',
}
# Третьим параметром передаём словарь context
return render(request, template, context)
Чтобы вывести данные из словаря context
, нужно лишь указать ключ словаря в нужном месте шаблона. Ключ указывают в двойных фигурных скобках {{ ... }}
:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ text }}</h1>
</body>
</html>
После рендеринга получится такой HTML-код:
<!DOCTYPE html>
<html>
<head>
<title>Анфиса для друзей</title>
</head>
<body>
<h1>Главная страница</h1>
</body>
</html>
И пользователь увидит такую страницу:
В качестве значений словаря context
можно передать в шаблон любые данные: строки, списки, словари, объекты классов. Процессор шаблонов упрощает и унифицирует обращение к свойствам и ключам переданных объектов. Он на лету определяет, что следует вызвать: свойство объекта, значение по ключу из словаря или метод. Обратиться к элементу словаря, свойству объекта или элементу списка можно через точечную нотацию:
{{ var_dict.key }} — обращение к ключу вложенного словаря
{{ var_instance.attribute }} — обращение к свойству или методу класса
{{ var_list.0 }} — обращение к элементу списка
Ветвление
Полученные данные можно обрабатывать прямо в шаблоне. Тег ветвления {% if %}
очень похож на оператор if/elif/else в языке Python. Обратите внимание: у тега {% if %}
обязательно должен быть закрывающий тег {% endif %}
:
{% if text == 'Главная страница' %}
Вы на главной странице.
{% elif text == 'Вложенная страница' %}
Вы в одном клике от главной страницы!
{% else %}
Мы понятия не имеем, где вы!
{% endif %}
Тот или иной вариант текста будет выведен в зависимости от того, какое значение передано в словаре context
под ключом text
.
Циклы
По итерируемым объектам можно пройтись циклом прямо в шаблоне. Синтаксис очень похож на аналогичные конструкции в Python. Если в словаре context
под ключом text
передана строка "Главная страница"
…
def some_view(request):
template = <путь к шаблону>
text = 'Главная страница'
context = {
'text': text,
}
return render(request, template, context)
…то можно перебрать эту строку в цикле:
<!DOCTYPE html>
<html>
<body>
{% for char in text %}
{% if forloop.first %}
<p>Начало цикла</p>
{% endif %}
<p>{{ char }}</p>
{# forloop хранит счётчик цикла и может определять разные состояния счётчика #}
{% if forloop.last %}
<p>Конец цикла</p>
{% endif %}
{% empty %}
<p>Если цикл пуст</p>
{% endfor %}
</body>
</html>
При рендеринге получится такой HTML-код:
<!DOCTYPE html>
<html>
<body>
<p>Начало цикла</p>
<p>Г</p>
<p>л</p>
<p>а</p>
<p>в</p>
<p>н</p>
<p>а</p>
<p>я</p>
<p> </p>
<p>с</p>
<p>т</p>
<p>р</p>
<p>а</p>
<p>н</p>
<p>и</p>
<p>ц</p>
<p>а</p>
<p>Конец цикла</p>
</body>
</html>
Текст на странице будет выглядеть оригинально, но странно:
В цикле применена переменная forloop
— это счётчик итераций цикла, у которого есть несколько полезных атрибутов, которые пригодятся в работе с циклом:forloop.counter
— номер текущей итерации цикла (начинает отсчёт с 1). forloop.counter0
— номер текущей итерации цикла «по-программистски» (начинает отсчёт с 0). forloop.revcounter
— количество итераций, оставшихся до конца цикла (начинает отсчёт с 1). forloop.revcounter0
— количество итераций, оставшихся до конца цикла (начинает отсчёт с 0).forloop.first
— возвращает True, если это первая итерация.forloop.last
— возвращает True, если это последняя итерация.Дополнительно в циклах шаблонов применяют необязательный тег {% empty %}
. Его ставят перед закрывающим тегом {% endfor %}
; после тега {% empty %}
размещают содержимое, которое будет показано, если цикл пуст. Документация по циклам в шаблонах интересна, полезна и познавательна.