Теги шаблонов Django: ветвления, циклы и ссылки
Ветвления
Тег ветвления (тег проверки условия) if похож на оператор ветвления в Python:
Скопировать кодHTML
{% if news %}
У вас {{ news|length }} обновлений новостей
{% elif is_holiday %}
Новостей нет, сегодня же праздник!
{% else %}
Сегодня нет новостей.
{% endif %}
В условиях {% if %} работают операторы сравнения <, >, <=, >=, !=, ==, логические операторы or, and, not, операторы тождественности is и вхождения in, круглые скобки и стандартные правила приоритета операций.
В условиях можно применять и фильтры:
Скопировать кодHTML
{% if news|length >= 100 %}
Сегодня больше сотни новостей! Что случилось?
{% endif %}
Циклы
Тег for выполняет определённый код для каждого элемента списка, переданного в цикл.
Допустим, из view-функции в шаблон передан словарь dict_data, в нём есть элемент items, в этом элементе содержится словарь, всё содержимое которого вместе с ключами нужно вывести на страницу:
Скопировать кодHTML
{% for key, value in dict_data.items %}
Ключ '{{ key }}': Значение '{{ value }}'
{% endfor %}
Помимо обычных переменных в циклах создаются и вспомогательные, они доступны в специальной переменной forloop:
- forloop.counter — текущий счетчик выполнений цикла, начинается с 1;
- forloop.counter0 — текущий счетчик выполнения цикла, начинается с 0;
- forloop.revcounter — сколько итераций осталось до конца цикла, начинается с 1;
- forloop.revcounter0 — сколько итераций осталось до конца цикла, начинается с 0;
- forloop.first — вернёт True на первой итерации цикла, в остальных случаях вернёт False;
- forloop.last — вернёт True на последней итерации цикла, в остальных случаях вернёт False;
- forloop.parentloop — если цикл был запущен внутри другого цикла, то в этой переменной находится переменная
forloop родительского цикла.
Необязательный тег {% empty %}, вложенный в for, сработает, если переданный в цикл список пуст:
Скопировать кодHTML
<ul>
{% for news in news_list %}
<li>{{ news.title }}</li>
{% empty %}
<li>Список новостей пуст.</li>
{% endfor %}
</ul>
То же самое можно написать и без {% empty %}, но получится громоздко:
Скопировать кодHTML
<ul>
{% if news_list %}
{% for news in news_list %}
<li>{{ news.title }}</li>
{% endfor %}
{% else %}
<li>Список новостей пуст.</li>
{% endif %}
</ul>
Вложенный в for тег {% ifchanged %} запоминает значение переданных параметров или своего тела между запусками цикла, — и если они не поменялись, скрывает его.
В этом листинге HTML-заголовок <h2> с названием месяца будет выводиться на страницу только если в предыдущей итерации цикла название месяца было другим.
Скопировать кодHTML
<h1>Архив новостей за {{ year }}</h1>
{% for news in news_items %}
{% ifchanged %}
<h2>{{ news.pub_date|date:"F" }}</h2>
{% endifchanged %}
<h3>{{ news.pub_date|date:"d.m.Y" }} | {{ news.title}}</h3>
{% endfor %}
В результате работы цикла получится примерно такой HTML-код:
Скопировать кодHTML
<h1>Архив новостей за 2019</h1>
<h2>Январь</h2>
<h3>1.01.2019 | С Новым Годом!</h3>
<h3>2.01.2019 | С Днём научной фантастики!</h3>
<h3>3.01.2019 | С Днём рождения соломинки для коктейлей!</h3>
<h2>Февраль</h2>
<h3>1.02.2019 | С Днём работника лифтового хозяйства!</h3>
<h3>2.02.2019 | С Днём сурка!</h3>
<h3>2.02.2019 | С Днём сурка!</h3>
<h3>2.02.2019 | С Днём сурка!</h3>
Без тега {% ifchanged %} получилось бы хуже:
Скопировать кодHTML
<h1>Архив новостей за 2019</h1>
<h2>Январь</h2>
<h3>1.01.2019 | С Новым Годом!</h3>
<h2>Январь</h2>
<h3>2.01.2019 | С Днём научной фантастики!</h3>
<h2>Январь</h2>
<h3>3.01.2019 | С Днём рождения соломинки для коктейлей!</h3>
<h2>Февраль</h2>
<h3>1.02.2019 | С Днём работника лифтового хозяйства!</h3>
<h2>Февраль</h2>
<h3>2.02.2019 | С Днём сурка!</h3>
<h2>Февраль</h2>
<h3>2.02.2019 | С Днём сурка!</h3>
<h2>Февраль</h2>
<h3>2.02.2019 | С Днём сурка!</h3>
Тег url
Тег {% url %} генерирует ссылки на страницы проекта. Из кода шаблона можно обратиться к именам адресов, зарегистрированных в списке urlpatterns в файле urls.py, и передать параметры, если они требуются:
Скопировать кодPYTHON
urlpatterns = [
path('', views.index, name='index'),
path('/detail/<int:pk>/', views.details, name='detail'),
...
]
Первый параметр тега url — это name пути из файла urls.py:
Скопировать кодHTML
<a href="{% url 'index' %}">Главная</a>
После name при необходимости передаются значения переменных, которые принимает path() в urls.py
Скопировать кодHTML
urlpatterns = [
path('/detail/<int:pk>/', views.details, name='detail'),
path('/<str:username>/<int:id>/', views.article, name='article'),
]
{# передаём один параметр #}
<a href="{% url 'detail' 1 %}">Подробнее об объекте 1</a> {# получится ссылка detail/1 #}
<a href="{% url 'detail' pk=1 %}">Подробнее об объекте 1</a>
<a href="{% url 'detail' pk=object.id %}">Подробнее об объекте {{ object.id }}</a>
{# передаём несколько параметров #}
<a href="{% url 'article' 'anton' 16 %}">Статья с ID=16, автор: anton</a>
<a href="{% url 'article' username='anton' id=16 %}">Статья с ID=16, автор: anton</a>
<a href="{% url 'article' username=article.username id=article.id %}">Статья с ID={{ article.id }}, автор: {{ article.username }}</a>