25. Шаблонизация верстки и язык шаблонов в Django.
Шаблонизация верстки
- Django динамически генерирует верстку.
- Для этого используется механизм шаблонов.
- Django поддерживает выбор бэкэнда шаблонизации.
- Шаблоны предоставляет API, через которое можно загружать и рендерить шаблоны независимо от конкретного бэкэнда.
- Загрузка - поиск шаблона и его предобработка.
- Рендеринг - преобразование шаблона и доп. данных текст (обычно html).
- Можно использовать или встроенный механизм Django шаблонов или какой-нибудь внешний шаблонизатор (например, jinja2).
Язык шаблонов Django
- Django-шаблон - строка или тестовый файл, содержащий элементы языка django-шаблонов и текст.
- Текст может быть разных форматов: html, json, csv, javascript и т.д.
Основные элементы языка шаблонов Django:
- переменные (и фильтры над ними)
- теги
Пример:
{% extends "base_generic.html" %} {% block title %}{{ section.title }}{% endblock %} {% block content %} <h1>{{ section.title }}</h1> {% for story in story_list %} <h2> <a href="{{ story.get_absolute_url }}"> {{ story.headline|upper }} </a> </h2> <p>{{ story.tease|truncatewords:"100" }}</p> {% endfor %} {% endblock %}
Переменные
- Записываются как {{ variable }} и {{ section.title }}.
- Переменная заменяется результатом её вычисления.
- Вычисление переменной:
- Если простое имя, то берётся соответствующее значение из переданного контекста шаблона.
- Если составное имя с точками, то последовательно происходит обращение разыменование частей пути значению.
- Когда в имени переменной содержится точка, то шаблонизатор пытается:
- получить значение по ключу из словаря (могут быть неожиданности, если хотели метод, например у defaultdict)
- использовать объект как атрибут или метод (вызывается без аргументов и результат используется как значение).
- индекс списка
Фильтры
Фильтры позволяют динамически выполнять цепочечные преобразования над значением переменной.
Пример применения фильтра lower к переменной name:
{{ name|lower }}
Цепочка фильтров:
{{ text|escape|linebreaks }}
Передача аргумента фильтру:
{{ text|truncatewords:30 }}
Ещё несколько примеров:
{{ value|default:"nothing" }} {{ value|length }} {{ value|filesizeformat }}
Тэги
Тэг - инструкция языка Django-шаблонов. Есть множество уже существующих, а также можно создавать свои.
Рассмотрим некоторые встроенные:
for In [ ]: <ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} </ul> if, elif, и else In [ ]: {% if athlete_list %} Number of athletes: {{ athlete_list|length }} {% elif athlete_in_locker_room_list %} Athletes should be out of the locker room soon! {% else %} No athletes. {% endif %} In [ ]: {% if athlete_list|length > 1 %} Team: {% for athlete in athlete_list %} ... {% endfor %} {% else %} Athlete: {{ athlete_list.0.name }} {% endif %}
Наследование шаблонов
Механизм наследования шаблонов позволяет переиспользовать общие части шаблонов.
Создаём базовый шаблон (шаблоны).
Помечаем в этих шаблонах специальным образом блоки.
* В шаблонах-потомках можем переопределять только эти блоки (или их часть), а остальное рендерится так, как у предка.
Базовый шаблон (base.html):
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>{% block title %}My amazing site{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block content %}{% endblock %} </div> </body> </html>
Дочерний шаблон:
{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
Пример результата:
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="content"> <h2>Entry one</h2> <p>This is my first entry.</p> <h2>Entry two</h2> <p>This is my second entry.</p> </div> </body> </html>