Как мы уже упоминали в предыдущей части – в систему шаблонов включены теги и шаблоны. В этой части мы кратко рассмотрим наиболее используемые из них.
Содержание
Теги (tags)
if/else
Тег {% if %}
проверяет значение переменной, и если оно True
(т.е. – она не пустая, и её булево значение не false
) – система отобразит всё, что указано между {% if %}
и {% endif %}
, например:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% endif %}
Тег {% else %}
не обязателен:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %}
Проверка значений в Python
В Python и в системе шаблонов Django следующие объекты будут иметь значение False
:
- пустой список ([]);
- пустой кортеж (());
- пустой словарь ({});
- пустая строка ('');
- ноль (0);
- специальный объект None;
- объект False (это очевидно);
- другие объекты, которые имеют собственное логическое поведение;
Всё остальное будет иметь значение True
Тег {% if %}
может принимать операторы and
, or
или not
для проверки нескольких переменных. Например:
{% if athlete_list and coach_list %} Both athletes and coaches are available. {% endif %} {% if not athlete_list %} There are no athletes. {% endif %} {% if athlete_list or coach_list %} There are some athletes or some coaches. {% endif %} {% if not athlete_list or coach_list %} There are no athletes or there are some coaches. {% endif %} {% if athlete_list and not coach_list %} There are some athletes and absolutely no coaches. {% endif %}
С тегом {% if %}
нельзя одновременно использовать операторы and
и or
, так как это сделает результат двусмысленным. Следующий пример будет некорректным:
{% if athlete_list and coach_list or cheerleader_list %}
Использование скобок для контроля над порядком операций недопустимо. Если вы всё же решили, что вам необходимо использование скобок – выполните логическую выборку вне шаблона, и передайте результат как отдельную переменную. Либо – используйте вложенный тег {% if %}
, например так:
{% if athlete_list %} {% if coach_list or cheerleader_list %} We have athletes, and either coaches or cheerleaders! {% endif %} {% endif %}
Множественное использование одного и того же логического оператора допустимо, но нельзя комбинировать различные операторы в одном теге. Например, следующий код будет работать верно:
{% if athlete_list or coach_list or parent_list or teacher_list %}
В Django нет тега {% elif %}
, но вы можете использовать вложенные теги {% if %}
для реализации задачи:
{% if athlete_list %} <p>Here are the athletes: {{ athlete_list }}.</p> {% else %} <p>No athletes are available.</p> {% if coach_list %} <p>Here are the coaches: {{ coach_list }}.</p> {% endif %} {% endif %}
Убедитесь, что все теги {% if %}
закрыты {% endif %}
. Иначе – Django вызовет исключение TemplateSyntaxError
.
for
Тег {% for %}
позволяет вам выполнять итерацию элементов в последовательности. Как и оператор for
в Python, синтаксис его выглядит как for X in Y
, где Y
– это последовательность элементов, а X
– имя переменной для использования в каждом цикле. Каждый раз при выполнении цикла – система шаблонов будет выполнять рендеринг всего, что заключено между {% for %}
и {% endfor %}
.
Например, вы можете использовать такой код для отображения списка спортсменов, заданных в списке athlete_list
:
<ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} </ul>
Вы может добавить reversed
, что бы выполнить итерацию в обратном порядке:
{% for athlete in athlete_list reversed %} ... {% endfor %}
Допустимо использование вложенных циклов {% for %}
:
{% for athlete in athlete_list %} <h1>{{ athlete.name }}</h1> <ul> {% for sport in athlete.sports_played %} <li>{{ sport }}</li> {% endfor %} </ul> {% endfor %}
Распространённая практика – проверять размер списка перед выполнением итерации, и выводить какой-то другое сообщение, если он пуст:
{% if athlete_list %} {% for athlete in athlete_list %} <p>{{ athlete.name }}</p> {% endfor %} {% else %} <p>There are no athletes. Only computer programmers.</p> {% endif %}
Так как такая проверка используется очень часто, поэтому тег for
поддерживает оператор {% empty %}
, который позволяет определить – что отображать, если список пустой. Следующий пример будет работать так же, как и предыдущий
{% for athlete in athlete_list %} <p>{{ athlete.name }}</p> {% empty %} <p>There are no athletes. Only computer programmers.</p> {% endfor %}
В тегах Django нет аналога оператора break
для выхода из цикла до его завершения. Если вы хотите выполнить подобное действие – измените саму переменную, участвующую в цикле так, что бы в ней были только те данные, которые должны быть в цикле (примечание: тут>>> есть примеры того, что имеется ввиду в этом параграфе). Аналогично – нет поддержки оператора continue
, который должен возвращать выполнение цикла к его началу (смотрите следующий раздел “Философия и Ограничения” далее в этой главе).
Внутри каждого цикла {% for %}
у вас есть доступ к переменной шаблона forloop
. Она содержит несколько атрибутов, которые могу предоставить вам информацию о процессе выполнения цикла:
-
forloop.counter
содержит в себе количество выполненных итераций цикла. Его индекс начинается с 1, а не с 0, и при первом выполнении циклаforloop.counter
будет равен 1. Например:{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}
-
forloop.counter0
аналогичен сforloop.counter
, но его отсчёт начинается с нуля, а не единицы. -
forloop.revcounter
содержит в себе количество оставшихся итераций. При первом выполнении цикла этот счётчик будет содержать в себе общее количество элементов в заданной циклу последовательности. При выполнении последней итерации – он будет равен 1. -
forloop.revcounter0
аналогиченforloop.revcounter
, с той разницей, что он заканчивается на 0, а не 1. При первом выполнении цикла – его значение будет равно общему количеству элементов -1, а при последнем – нулю. -
forloop.first
– логическое (булево) значение, содержитTrue
при первом выполнении цикла. Удобен для особых случаев, например:{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %}
-
forloop.last
– аналогиченforloop.first
, но будетTrue
при последнем выполнении цикла. Часто используется для добавления|
между элементами списка ссылок:{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
Результат будет выглядеть так:
Link1 | Link2 | Link3 | Link4
Другой пример использования – добавление запятой между словами в списке:
Favorite places: {% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}
-
forloop.parentloop
– ссылка на родительский цикл в случаях с вложенными циклами, например:{% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }}</td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table> {% endfor %}
Специальная переменная forloop
допустима только в циклах. Как только парсер шаблона достигнет {% endfor %}
– переменная forloop
исчезнет.
Context и переменная forloop
Внутри блока {% for %}
существующие переменные “сдвигаются”, что бы избежать перезаписи значения специальной переменной forloop
. Как правило, вам не стоит переживать на этот счёт, но если вы используете свою переменную forloop
(хотя это не рекомендуется), она будет названа forloop.parentloop
внутри всего блока {% for %}
.
ifequal/ifnotequal
Система шаблонов Django разработана не как язык программирования, и в ней недопустимо использование обычных операторов Python. Однако, очень часто требуется сравнить две переменные и отобразить что-либо, если они не идентичны – для этого в Django используется тег {% ifequal %}
.
Тег {% ifequal %}
сравнивает два значения, и отображает всё, что задано между {% ifequal %}
и {% endifequal %}
если значения одинаковы.
В этом примере сравниваются две переменные шаблона – user
и currentuser
:
{% ifequal user currentuser %} <h1>Welcome!</h1> {% endifequal %}
Аргументами можно использовать непосредственно строку, заключённую в одинарные или двойные кавычки:
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% endifequal %} {% ifequal section "community" %} <h1>Community</h1> {% endifequal %}
Как и в теге {% if %}
, в {% ifequal %}
можно использовать {% else %}
:
{% ifequal section 'sitenews' %} <h1>Site News</h1> {% else %} <h1>No News Here</h1> {% endifequal %}
В качестве аргументов можно использовать только переменные, строки, целые и десятичные числа:
{% ifequal variable 1 %} {% ifequal variable 1.23 %} {% ifequal variable 'foo' %} {% ifequal variable "foo" %}
Любые другие типы переменных, такие как словари, списки и логические типы – недопустимы. Вот неправильные примеры использования {% ifequal %}
:
{% ifequal variable True %} {% ifequal variable [1, 2, 3] %} {% ifequal variable {'key': 'value'} %}
Если вам необходимо проверить что-либо истинно или ложно – используйте тег {% if %}
вместо {% ifequal %}
.
Комментарии
Как и в HTML или Python, система шаблонов Django поддерживает добавление комментариев в код. Что бы обозначить его – используйте тег {# #}
:
{# This is a comment #}
Этот комментарий не будет отображён при рендеринге шаблона.
Комментарии с использованием {# #}
могут быть только однострочными – такое ограничение ускоряет парсинг шаблона.
Если вы хотите использовать многострочный комментарий – используйте тег {% comment %}
, например:
{% comment %} This is a multi-line comment. {% endcomment %}
Фильтры
Как уже было сказано в этой главе ранее, фильтры шаблона являются самым простым и удобным способом изменить значение переменной перед её отображением. Фильтры используют символ pipe |
, например так:
{{ name|lower }}
Таким образом будет выведено значение переменной {{ name }}
после применения фильтра lower
, который переведёт текст в нижний регистр символов.
Фильтры могут быть объединены в цепочки и использованы вместе, таким образом вывод одного фильтра будет передан на обработку второму фильтру. В следующем примере первый элемент списка попадает под фильтр, а потом изменяется в заглавные символы:
{{ my_list|first|upper }}
Некоторые фильтры могут принимать аргументы. Аргументы фильтра указываются после двоеточия и в двойных кавычках:
{{ bio|truncatewords:"30" }}
Так будут выведены первые 30 символов переменной bio
.
Вот несколько наиболее полезных фильтров:
-
addslashes
– добавляет символы косой черты перед любыми другими слешами, одинарными или двойными кавычками. Полезно при использовании JavaScript в коде. -
date
– форматирование объектовdate
илиdatetime
в соответствии с заданными параметрами, например:{{ pub_date|date:"F j, Y" }}
-
length
– возвращает длину значения переменной. Для списка – количество элементов, для строки – количество символов. Работает с любым объектом, который поддерживает метод__len__()
.
Продолжение – Django Book: философия и ограничения.