Django_-_podrobnoe_rukovodstvo
.pdf490 |
Приложение E. Встроенные шаблонные теги и фильтры |
Как видите, в теге if может присутствовать необязательная часть {% else %}, которая выполняется, когда проверка завершается неудачно.
Внутри тега if можно использовать операторы and и or для комбинирования нескольких проверок, а также not для отрицания последующего условия:
{% if athlete_list and coach_list %} Есть спортсмены и тренеры.
{% endif %}
{% if not athlete_list %} Спортсменов нет.
{% endif %}
{% if athlete_list or coach_list %} Есть спортсмены или тренеры.
{% endif %}
{% if not athlete_list or coach_list %}
Нет спортсменов или есть тренеры (да, перевод булевских выражений на естественный язык звучит ужасно, но тут уж мы не виноваты).
{% endif %}
{% if athlete_list and not coach_list %} Есть спортсмены, но нет ни одного тренера.
{% endif %}
В теге if не допускается употреблять одновременно операторы and и or, потому что порядок их выполнения неоднозначен. Например, такая конструкция недопустима:
{% if athlete_list and coach_list or cheerleader_list %}
Если для формулирования сложного условия необходима комбинация операторов and и or, воспользуйтесь вложенными тегами if. Например:
{% if athlete_list %}
{% if coach_list or cheerleader_list %}
Есть спотсмены и либо тренеры, либо группа поддержки! {% endif %}
{% endif %}
При этом допускается несколько раз употреблять один и тот же логический оператор. Например, такая конструкция допустима:
{% if athlete_list or coach_list or parent_list or teacher_list %}
ifchanged
Проверяет, изменилось ли значение по сравнению с предыдущей итерацией цикла.
Справочник по встроенным тегам |
491 |
Тег ifchanged употребляется внутри цикла; возможные варианты использования:
•• Сравнивает содержимое, предназначенное для вывода, с тем, что было выведено на предыдущей итерации, и производит вывод, только если обнаружены изменения. Например, выведем список дат, печатая месяц, только если он изменился по сравнению с предыдущей датой:
<h1Архив за {{ year }}</h1>
{% for date in days %}
{% ifchanged %}<h3>{{ date|date:”F” }}</h3>{% endifchanged %} <a href=”{{ date|date:”M/d”|lower }}/”>{{ date|date:”j” }}</a>
{% endfor %}
•• Если задана переменная, то проверяет, изменилось ли ее значение. Например, в следующем фрагменте дата выводится при каждой смене, но час печатается, только если изменились одновременно и час, и дата:
{% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %} {% ifchanged date.hour date.date %}
{{ date.hour }} {% endifchanged %}
{% endfor %}
В теге ifchanged может присутствовать необязательная часть {% else %}, которая отображается, если значение не изменилось:
{% for match in matches %}
<div style=”background-color:
{% ifchanged match.ballot_id %} {% cycle red,blue %}
{% else %} grey
{% endifchanged %} “>{{ match }}</div>
{% endfor %}
ifequal
Выводит содержимое блока, если оба аргумента тега равны. Например:
{% ifequal user.id comment.user_id %}
...
{% endifequal %}
Как и в теге {% if %}, может присутствовать необязательная часть {% else %}.
В роли аргументов допускается использовать строковые литералы, то есть следующая конструкция тоже допустима:
492 |
|
Приложение E. Встроенные шаблонные теги и фильтры |
|
{% |
ifequal user.username “adrian” %} |
|
|
... |
|
{% |
endifequal %} |
Аргумент можно сравнивать только с шаблонными переменными или строками. Не допускается сравнивать с объектами Python, например, True или False. В случае такой необходимости пользуйтесь тегом if.
ifnotequal
Аналогичен ifequal, но проверяется различие аргументов.
include
Загружает шаблон и производит его отображение в текущем контексте. Таким способом можно включать один шаблон в другой.
Имя шаблона может быть переменной или строковым литералом, заключенным в одиночные или двойные кавычки.
Вследующем примере включается содержимое шаблона “foo/bar.html”:
{% include “foo/bar.html” %}
Аздесь включается содержимое шаблона, имя которого содержится в переменной template_name:
{% include template_name %}
Отображение включаемого шаблона производится в контексте включающего шаблона. В следующем примере выводится строка “Привет, Джон”:
•• Контекст: переменная person имеет значение “Джон”.
•• Шаблон:
{% include “name_snippet.html” %}
•• Шаблон name_snippet.html:
Привет, {{ person }}
См. также: {% ssi %}.
load
Загружает набор пользовательских шаблонных тегов. О библиотеках пользовательских тегов см. главу 9.
now
Выводит текущую дату в соответствии с указанной строкой формата.
Синтаксис определения формата такой же, как в PHP-функции date() (http://php.net/date) с некоторыми дополнениями.
В табл. E.2 показаны все имеющиеся спецификаторы формата.
Справочник по встроенным тегам |
493 |
||
Таблица E.2. Допустимые спецификаторы формата даты |
|||
|
Спецификатор |
Описание |
Пример вывода |
|
|
|
|
|
a |
‘a.m.’ или ‘p.m.’ (Формат отличается |
‘a.m.’ |
|
|
от принятого в PHP наличием точек, |
|
|
|
в соответствии со стилем агентства |
|
|
|
«Ассошиэйтед Пресс») |
|
|
A |
‘AM’ или ‘PM’ |
‘AM’ |
|
b |
Трехбуквенное сокращенное |
‘jan’ |
|
|
название месяца, записанное |
|
|
|
строчными буквами |
|
BНе реализовано
d |
Двузначный день месяца, |
От ‘01’ до ‘31’ |
|
с начальным нулем |
|
D |
Трехбуквенное сокращенное |
‘Fri’ |
|
название дня недели |
|
fВремя в 12-часовом формате с часами ‘1’, ‘1:30’ и минутами. Если количество минут
равно нулю, минуты отбрасываются. Добавлен в Django.
F |
Полное название месяца |
‘January’ |
g |
Час в 12-часовом формате без |
от ‘1’ до ‘12’ |
|
начального нуля |
|
G |
Час в 24-часовом формате без |
от ‘0’ до ‘23’ |
|
начального нуля |
|
h |
Час в 12-часовом формате |
от ‘01’ до ‘12’ |
H |
Час в 24-часовом формате |
от ‘00’ до ‘23’ |
i |
Минуты |
от ‘00’ до ‘59’ |
IНе реализовано
j |
День месяца без начального нуля |
от ‘1’ до ‘31’ |
l |
Полное название дня недели |
‘Friday’ |
LБулевский признак високосного года True или False
m |
Номер месяца, две цифры |
от ‘01’ до ‘12’ |
|
с начальным нулем |
|
M |
Трехбуквенное сокращенное |
‘Jan’ |
|
название месяца |
|
n |
Номер месяца без начального нуля |
от ‘1’ до ‘12’ |
N |
Сокращенное название месяца |
‘Jan.’, ‘Feb.’, |
|
в стиле агентства «Ассошиэйтед |
‘March’, ‘May’ |
|
Пресс». Добавлен в Django |
|
|
|
494 |
|
Приложение E. Встроенные шаблонные теги и фильтры |
||
Таблица E.2. (Продолжение) |
|
|
||
|
Спецификатор |
Описание |
Пример вывода |
|
|
|
|
|
|
|
O |
Разница с Гринвичским временем |
‘+0200’ |
|
|
|
в часах |
|
|
|
P |
Время в 12-часовом формате |
‘1 a.m.’, ‘1:30 p.m.’, |
|
|
|
с часами, минутами и признаком |
‘midnight’, ‘noon’, |
|
|
|
‘a.m.’/‘p.m.’, причем число минут |
‘12:30 p.m.’ |
|
|
|
отбрасывается, если оно равно нулю. |
|
|
|
|
Полдень и полночь обозначаются |
|
|
|
|
специальными строками ‘midnight’ |
|
|
|
|
и ‘noon’ соответственно. Добавлено |
|
|
|
|
в Django |
|
|
|
r |
Дата в формате RFC 2822 |
‘Thu, 21 Dec 2000 |
|
|
|
|
16:01:07 |
+0200’ |
|
s |
Секунды, два знака с начальным |
от ‘00’ до ‘59’ |
|
|
|
нулем |
|
|
|
S |
Английское окончание порядкового |
‘st’, ‘nd’, ‘rd’, ‘th’ |
|
|
|
числительного для номера дня |
|
|
|
|
в месяце, две буквы |
|
|
|
t |
Количество дней в указанном месяце |
от 28 до 31 |
|
|
T |
Часовой пояс, установленный на |
‘EST’, ‘MDT’ |
|
|
|
данном компьютере |
|
|
UНе реализовано
w |
Номер дня недели без начального |
от ‘0’ (воскресенье) |
|
нуля |
до ‘6’ (суббота) |
W |
Номер недели в году по стандарту |
от 1 до 53 |
|
ISO-8601, неделя начинается |
|
|
с понедельника |
|
y |
Двузначный номер года |
‘99’ |
Y |
Четырехзначный номер года |
‘1999’ |
z |
Номер дня в году |
от 0 до 365 |
ZСмещение часового пояса в секундах. от -43200 до 43200 Смещение для поясов к западу от
UTC отрицательно, к востоку – положительно
Например:
Сейчас {% now “jS F Y H:i” %}
Если в строку формата потребуется добавить символ, совпадающий со спецификатором, его можно экранировать символом обратного слеша. В следующем примере был экранирован символ ‘f’, потому что иначе он
Справочник по встроенным тегам |
495 |
интерпретировался бы как спецификатор для вывода времени. Символ же ‘o’ экранировать не нужно, потому что такого спецификатора фор-
мата не существует:
It is the {% now “jS o\f F” %}
В результате будет выведена строка «It is the 4th of September».
regroup
Перегруппировывает список похожих объектов по общему атрибуту.
Работу этого хитрого тега лучше всего проиллюстрировать на примере. Предположим, что people – список людей, информация о каждом из которых представлена словарем с ключами first_name (имя), last_name (фамилия) и gender (пол):
people = [
{‘first_name’: ‘Джордж’, ‘last_name’: ‘Буш’, ‘gender’: ‘Мужской’}, {‘first_name’: ‘Билл’, ‘last_name’: ‘Клинтон’, ‘gender’: ‘Мужской’}, {‘first_name’: ‘Маргарет’, ‘last_name’: ‘Тэтчер’, ‘gender’: ‘Женский’}, {‘first_name’: ‘Кондолиза’, ‘last_name’: ‘Райс’, ‘gender’: ‘Женский’}, {‘first_name’: ‘Пэт’, ‘last_name’: ‘Смит’, ‘gender’: ‘Неизвестен’},
]
И вы хотите вывести иерархический список, упорядоченный по полу, например:
•• Мужской:
•• Джордж Буш
•• Билл Клинтон
•• Женский:
•• Маргарет Тэтчер
•• Кондолиза Райс
•• Неизвестен:
•• Пэт Смит
Для группировки по полу можно воспользоваться тегом {% regroup %}, как показано ниже:
{% regroup people by gender as gender_list %} <ul>
{% for gender in gender_list %} <li>{{ gender.grouper }} <ul>
{% for item in gender.list %}
<li>{{ item.first_name }} {{ item.last_name }}</li> {% endfor %}
</ul>
</li>
496 |
Приложение E. Встроенные шаблонные теги и фильтры |
{% endfor %} </ul>
Разберемся, что здесь происходит. Тег {% regroup %} принимает три аргумента: список, который нужно перегруппировать; атрибут, по которому производится группировка, и имя результирующего списка. В данном случае мы хотим перегруппировать список people по атрибуту gender и назвать результат gender_list.
Тег {% regroup %} порождает список (в нашем случае gender_list) групповых объектов. У каждого группового объекта есть два атрибута:
•• grouper: имя атрибута, по которому образована группа (например, строка “Мужской” или “Женский”).
•• list: список всех элементов этой группы (например, список людей, для которых gender=’Мужской’).
Отметим, что тег {% regroup %} не сортирует входные данные! В нашем примере предполагалось, что список people изначально отсортирован по атрибуту gender. Если бы это было не так, то в результате перегруппировки образовалось бы несколько групп с одним и тем же значением пола. Например, пусть исходный список people выглядит так (обратите внимание, что мужчины не сгруппированы вместе):
people = [
{‘first_name’: ‘Билл’, ‘last_name’: ‘Клинтон’, ‘gender’: ‘Мужской’}, {‘first_name’: ‘Пэт’, ‘last_name’: ‘Смит’, ‘gender’: ‘Неизвестен’}, {‘first_name’: ‘Маргарет’, ‘last_name’: ‘Тэтчер’, ‘gender’: ‘Женский’}, {‘first_name’: ‘Джордж’, ‘last_name’: ‘Буш’, ‘gender’: ‘Мужской’}, {‘first_name’: ‘Кондолиза’, ‘last_name’: ‘Райс’, ‘gender’: ‘Женский’},
]
Если передать такой список people предыдущему фрагменту шаблона {% regroup %}, он породит такой результат:
•• Мужской:
•• Билл Клинтон
•• Неизвестен:
•• Пэт Смит
•• Женский:
•• Маргарет Тэтчер
•• Мужской:
•• Джордж Буш
•• Женский:
•• Кондолиза Райс
Чтобы решить эту проблему, проще всего заранее отсортировать список данных и только потом передавать его в шаблон.
Справочник по встроенным тегам |
497 |
Есть и другое решение – отсортировать данные прямо в шаблоне с помощью фильтра dictsort. Но применимо оно только в случае, когда данные представляют собой список словарей:
{% regroup people|dictsort:”gender” by gender as gender_list %}
spaceless
Удаляет пробельные символы между HTML-тегами (пробелы, символы табуляции и перехода на новую строку). Например:
{% spaceless %} <p>
<a href=”foo/”>Foo</a>
</p>
{% endspaceless %}
Врезультате получится такая HTML-разметка:
<p><a href=”foo/”>Foo</a></p>
Удаляются только пробельные символы между тегами, но не между тегами и текстом. В следующем примере пробелы, окружающие слово Привет, не удаляются:
{% spaceless %} <strong>
Привет
</strong>
{% endspaceless %}
ssi
Выводит содержимое указанного файла на страницу.
Как и тег include, {% ssi %} включает содержимое другого файла, заданного абсолютным путем:
{% ssi /home/html/ljworld.com/includes/right_generic.html %}
Если присутствует необязательный параметр “parsed”, то содержимое включаемого файла обрабатывается как код шаблона в текущем контексте:
{% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}
Отметим, что при использовании тега {% ssi %} необходимо определить в конфигурационном файле Django параметр ALLOWED_INCLUDE_ROOTS для пущей безопасности.
См. также {% include %}.
templatetag
Выводит один из синтаксических элементов шаблонных тегов.
498 |
Приложение E. Встроенные шаблонные теги и фильтры |
Поскольку в системе шаблонов нет механизма экранирования, то для буквального вывода синтаксических элементов шаблона приходится использовать тег {% templatetag %}.
Все допустимые аргументы этого тега перечислены в табл. E.3.
Таблица E.3. Аргументы тега templatetag
Аргумент |
Выводит |
|
|
openblock |
{% |
closeblock |
%} |
openvariable |
{{ |
closevariable |
}} |
openbrace |
{ |
closebrace |
} |
opencomment |
{# |
closecomment |
#} |
|
|
url
Возвращает абсолютный URL (то есть URL без доменного имени), со-
ответствующий указанной функции представления, с необязательными параметрами. Таким способом можно формировать ссылки, не зашивая их URL-адреса в шаблоны и, следовательно, не нарушая прин-
цип DRY:
{% url path.to.some_view arg1,arg2,name1=value1 %}
Первый аргумент – это путь к функции представления в виде package. package.module.function. Все остальные аргументы необязательны. Если они присутствуют, то должны разделяться запятыми и будут использоваться как позиционные и именованные параметры в строке запроса. Все аргументы, указанные в конфигурации URL, должны быть заданы обязательно.
Пусть, например, имеется представление app_views.client, для которого в образце URL указан идентификатор клиента (здесь client() – метод, определенный в файле представления app_views.py). Этот образец мог бы выглядеть так:
(‘^client/(\d+)/$’, ‘app_views.client’)
Если конфигурация URL этого приложения включена в конфигурацию URL всего проекта:
(‘^clients/’, include(‘project_name.app_name.urls’))
Справочник по встроенным фильтрам |
499 |
то в шаблоне можно создать ссылку на представление следующим образом:
{% url app_views.client client.id %}
Этот тег выведет строку /clients/client/123/.
widthratio
При создании столбчатых диаграмм и других подобных вещей этот тег вычисляет отношение данного значения к максимальному, а затем умножает результат на константу. Например:
<img src=”bar.gif” height=”10” width=”{% widthratio this_value max_value 100 %}” />
Если this_value равно 175, а max_value равно 200, то ширина изображения
впримере выше составит 88 пикселов (так как 175 / 200 = 0.875, 0.875 * 100 = 87.5, что после округления дает 88).
with
Кэширует составную переменную под простым именем. Это полезно, когда требуется вызвать дорогостоящий метод (например, несколько раз обращающийся к базе данных). Например:
{% with business.employees.count as total %} {{ total }} employee{{ total|pluralize }}
{% endwith %}
Кэшированная переменная (в данном примере total) существует только в блоке между тегами {% with %} и {% endwith %}.
Справочник по встроенным фильтрам add
Прибавляет аргумент к значению, например:
{{ value|add:”2” }}
Если value равно 4, то получится 6.
addslashes
Вставляет символы слеша перед кавычками. Полезно, например, для экранирования строк в формате CSV.
capfirst
Переводит первый символ значения в верхний регистр.