Шаблоны
Будучи веб-фреймворком, Django нуждается в удобном способе динамического генерирования HTML. Наиболее распространённый подход использует шаблоны. Шаблон содержит статические части желаемого HTML-вывода, а также специальный синтаксис, описывающий, как будет вставлено динамическое содержимое. Для практического примера создания HTML-страниц с шаблонами см. Урок 3.
Проект Django может быть настроен с одним или несколькими движками шаблонов (или даже с нулём, если вы не используете шаблоны). Django поставляется с встроенными бэкендами для собственной системы шаблонов, творчески названной языком шаблонов Django (DTL), и для популярной альтернативы Jinja2. Бэкэнды для других языков шаблонов могут быть доступны от сторонних разработчиков. Вы также можете написать свой собственный пользовательский бэкенд, см. Пользовательский бэкенд шаблонов
Django определяет стандартный API для загрузки и рендеринга шаблонов независимо от бэкенда. Загрузка включает в себя поиск шаблона для данного идентификатора и его предобработку, обычно компиляцию в представление в памяти. Рендеринг означает интерполяцию шаблона с данными контекста и возвращение результирующей строки.
Язык шаблонов Django — собственная система шаблонов Django. До Django 1.8 это был единственный доступный встроенный вариант. Это хорошая библиотека шаблонов, хотя она довольно категорична и имеет несколько особенностей. Если у вас нет веской причины выбрать другой бэкенд, вы должны использовать DTL, особенно если вы пишете подключаемый модуль и планируете распространять шаблоны. Приложения Django contrib, которые включают в себя шаблоны, такие как django.contrib.admin, используют DTL.
По историческим причинам как общая поддержка движков шаблонов, так и реализация языка шаблонов Django находятся в пространстве имён django.template.
Предупреждение
Система шаблонов не защищена от ненадежных авторов шаблонов. Например, сайт не должен разрешать своим пользователям предоставлять собственные шаблоны, поскольку авторы шаблонов могут выполнять такие действия, как атаки XSS и доступ к свойствам переменных шаблонов, которые могут содержать конфиденциальную информацию.
Язык шаблонов Django
Синтаксис
О данной секции
Это обзор синтаксиса языка шаблонов Django. Для получения подробностей см. справочник по синтаксису языка.
Шаблон Django — это текстовый документ или строка Python, помеченные с использованием языка шаблонов Django. Некоторые конструкции распознаются и интерпретируются движком шаблонов. Основные из них — переменные и теги.
Шаблон рендерится с контекстом. Рендеринг заменяет переменные их значениями, которые ищут в контексте, и выполняет теги. Всё остальное выводится как есть.
Синтаксис языка шаблонов Django включает четыре конструкции.
Переменные
Переменная выводит значение из контекста, который является объектом, похожим на словарь, сопоставляющим ключи со значениями.
Переменные заключены в {{ и }}, например:
My first name is {{ first_name }}. My last name is {{ last_name }}.
С контекстом {'first_name': 'John', 'last_name': 'Doe'}, этот шаблон рендерится в:
My first name is John. My last name is Doe.
Обращение к элементам словаря, поиск атрибутов и индексов списков реализуются с помощью нотации точки:
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
Если переменная разрешается в вызываемый объект, система шаблонов вызовет его без аргументов и будет использовать его результат вместо вызываемого объекта.
Фильтры
Фильтры преобразуют значения переменных и аргументов тегов.
Они выглядят так:
{{ django|title }}
С контекстом {'django': 'the web framework for perfectionists with
deadlines'}, этот шаблон рендерится в:
The Web Framework For Perfectionists With Deadlines
Некоторые фильтры принимают аргумент:
{{ my_date|date:"Y-m-d" }}
Доступна ссылка на встроенные фильтры, а также инструкции по написанию пользовательских фильтров.
Комментарии
Комментарии выглядят так:
{# this won't be rendered #}
Тег {% comment %} предоставляет многострочные комментарии.
Компоненты
О данной секции
Это обзор API языка шаблонов Django. Для получения подробностей см. справочник по API.
Движок
django.template.Engine инкапсулирует экземпляр системы шаблонов Django. Основная причина прямого создания экземпляра Engine — использование языка шаблонов Django вне проекта Django.
django.template.backends.django.DjangoTemplates — это тонкий обертка, адаптирующая django.template.Engine к API бэкенда шаблонов Django.
Шаблон
django.template.Template представляет собой скомпилированный шаблон. Шаблоны получают с помощью Engine.get_template() или Engine.from_string().
Аналогично, django.template.backends.django.Template — это тонкий обертка, адаптирующая django.template.Template к общему API шаблонов.
Контекст
django.template.Context хранит метаданные в дополнение к данным контекста. Он передаётся Template.render() для рендеринга шаблона.
django.template.RequestContext — это подкласс Context, который хранит текущий HttpRequest и выполняет обработчики контекста шаблона.
В общем API нет эквивалентной концепции. Данные контекста передаются в обычном dict, а текущий HttpRequest передаётся отдельно, если это необходимо.
Загрузчики
Загрузчики шаблонов отвечают за поиск шаблонов, их загрузку и возвращение объектов Template.
Django предоставляет несколько встроенных загрузчиков шаблонов и поддерживает пользовательские загрузчики шаблонов.
Обработчики контекста
Обработчики контекста — это функции, которые принимают текущий HttpRequest в качестве аргумента и возвращают dict данных, которые должны быть добавлены в контекст рендеринга.
Их основное использование — добавление общих данных, используемых всеми шаблонами, в контекст без повторения кода в каждом представлении.
Django предоставляет множество встроенных обработчиков контекста, и вы также можете реализовать свои собственные дополнительные обработчики контекста.
Поддержка движков шаблонов
Настройка
Движки шаблонов настраиваются с помощью параметра TEMPLATES. Это список конфигураций, по одной для каждого движка. Значение по умолчанию пустое. Значение, сгенерированное командой startproject, определяет более полезное значение:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
# ... some options here ...
},
},
]
BACKEND — это строка пути к классу движка шаблонов в формате Python, реализующего API бэкенда Django для шаблонов. Встроенные бэкенды — django.template.backends.django.DjangoTemplates и django.template.backends.jinja2.Jinja2.
Поскольку большинство движков загружают шаблоны из файлов, верхнеуровневая конфигурация каждого движка содержит два общих параметра:
-
DIRSопределяет список директорий, где движок должен искать исходные файлы шаблонов в порядке поиска. -
APP_DIRSуказывает, должен ли движок искать шаблоны внутри установленных приложений. Каждый бэкенд определяет стандартное имя подкаталога внутри приложений, где должны храниться его шаблоны.
Хотя это нечасто встречается, можно настроить несколько экземпляров одного и того же бэкенда с разными параметрами. В этом случае вы должны определить уникальное значение NAME для каждого движка.
OPTIONS содержит параметры, специфичные для бэкенда.
Использование
Модуль django.template.loader определяет две функции для загрузки шаблонов.
-
get_template(template_name, using=None)[source] -
Эта функция загружает шаблон с заданным именем и возвращает объект
Template.Точный тип возвращаемого значения зависит от бэкенда, который загрузил шаблон. Каждый бэкенд имеет свой собственный класс
Template.get_template()перебирает каждый движок шаблонов по порядку, пока один из них не выполнится успешно. Если шаблон не найден, генерируется исключениеTemplateDoesNotExist. Если шаблон найден, но содержит неверный синтаксис, генерируется исключениеTemplateSyntaxError.Поиск и загрузка шаблонов зависит от бэкенда и конфигурации каждого движка.
Если вы хотите ограничить поиск конкретным движком шаблонов, передайте имя бэкенда движка,
NAMEв аргументusing.
-
select_template(template_name_list, using=None)[source] -
select_template()аналогична функцииget_template(), за исключением того, что она принимает список имён шаблонов. Она перебирает каждое имя по порядку и возвращает первый существующий шаблон.
Если загрузка шаблона завершается неудачей, могут быть сгенерированы следующие два исключения, определённые в django.template:
-
exception TemplateDoesNotExist(msg, tried=None, backend=None, chain=None)[source] -
Это исключение генерируется, когда шаблон не найден. Оно принимает следующие необязательные аргументы для заполнения отчёта о неполадках шаблона на странице отладки:
-
backend -
Экземпляр бэкенда шаблона, из которого возникло исключение.
-
tried -
Список источников, которые были проверены при поиске шаблона. Он представлен списком кортежей, содержащих
(origin, status), гдеorigin— объект происхождения, аstatus— строка с причиной, по которой шаблон не был найден. -
chain -
Список промежуточных исключений
TemplateDoesNotExist, сгенерированных при попытке загрузки шаблона. Это используется функциями, такими какget_template(), которые пытаются загрузить заданный шаблон из нескольких движков.
-
-
exception TemplateSyntaxError(msg)[source] -
Это исключение генерируется, когда шаблон был найден, но содержит ошибки.
Объекты Template, возвращаемые функциями get_template() и select_template(), должны предоставлять метод render() со следующим сигнатуром:
-
Template.render(context=None, request=None) -
Отображает этот шаблон с заданным контекстом.
Если
contextпредоставлен, он должен бытьdict. Если он не предоставлен, движок отобразит шаблон с пустым контекстом.Если
requestпредоставлен, он должен бытьHttpRequest. Тогда движок должен сделать его, а также маркер CSRF, доступным в шаблоне. Как это достигается, зависит от каждого бэкенда.
Вот пример алгоритма поиска. Для этого примера настройка TEMPLATES имеет следующий вид:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/home/html/example.com",
"/home/html/default",
],
},
{
"BACKEND": "django.template.backends.jinja2.Jinja2",
"DIRS": [
"/home/html/jinja2",
],
},
]
Если вы вызовете get_template('story_detail.html'), вот файлы, которые Django будет искать в указанном порядке:
-
/home/html/example.com/story_detail.html('django'движок) -
/home/html/default/story_detail.html('django'движок) -
/home/html/jinja2/story_detail.html('jinja2'движок)
Если вы вызовете select_template(['story_253_detail.html', 'story_detail.html']), вот что Django будет искать:
-
/home/html/example.com/story_253_detail.html('django'движок) -
/home/html/default/story_253_detail.html('django'движок) -
/home/html/jinja2/story_253_detail.html('jinja2'движок) -
/home/html/example.com/story_detail.html('django'движок) -
/home/html/default/story_detail.html('django'движок) -
/home/html/jinja2/story_detail.html('jinja2'движок)
Когда Django найдёт существующий шаблон, поиск прекращается.
Используйте django.template.loader.select_template() для большей гибкости
Вы можете использовать select_template() для гибкой загрузки шаблонов. Например, если вы написали новостную статью и хотите, чтобы некоторые статьи имели пользовательские шаблоны, используйте что-то вроде select_template(['story_%s_detail.html' % story.id,
'story_detail.html']). Это позволит вам использовать пользовательский шаблон для отдельной статьи с резервным шаблоном для статей, у которых нет пользовательских шаблонов.
Возможен и предпочтительнее организовать шаблоны в подкаталогах внутри каждой директории, содержащей шаблоны. Принято создавать подкаталог для каждой Django-приложения, с подкаталогами внутри этих подкаталогов по мере необходимости.
Сделайте это для вашего удобства. Хранение всех шаблонов в корневой директории одного каталога становится беспорядочным.
Чтобы загрузить шаблон, который находится в подкаталоге, используйте слеш, например:
get_template("news/story_detail.html")
Используя тот же параметр TEMPLATES, что и выше, Django будет пытаться загрузить следующие шаблоны:
-
/home/html/example.com/news/story_detail.html('django'движок) -
/home/html/default/news/story_detail.html('django'движок) -
/home/html/jinja2/news/story_detail.html('jinja2'движок)
Кроме того, чтобы сократить повторяющиеся действия по загрузке и отображению шаблонов, Django предоставляет функцию-обёртку, которая автоматизирует этот процесс.
-
render_to_string(template_name, context=None, request=None, using=None)[source] -
render_to_string()загружает шаблон, как иget_template(), и сразу же вызывает его методrender(). Она принимает следующие аргументы.-
template_name -
Имя шаблона для загрузки и отображения. Если это список имён шаблонов, Django использует
select_template()вместоget_template()для поиска шаблона. -
context -
dict, используемый в качестве контекста шаблона для отображения. -
request -
Необязательный
HttpRequest, который будет доступен во время процесса отображения шаблона. -
using -
Необязательное имя бэкенда шаблона
NAME. Поиск шаблона будет ограничен этим движком.
Пример использования:
from django.template.loader import render_to_string rendered = render_to_string("my_template.html", {"foo": "bar"}) -
См. также render() — функцию-обёртку, которая вызывает render_to_string() и передаёт результат в HttpResponse, подходящий для возврата из представления.
И наконец, вы можете напрямую использовать настроенные движки:
-
engines -
Движки шаблонов доступны в
django.template.engines:from django.template import engines django_engine = engines["django"] template = django_engine.from_string("Hello {{ name }}!")Ключ поиска —
'django'в данном примере — это имя бэкенда движкаNAME.
Встроенные бэкэнды
-
class DjangoTemplates[source]
Установите BACKEND на 'django.template.backends.django.DjangoTemplates', чтобы настроить движок шаблонов Django.
Когда APP_DIRS имеет значение True, движки шаблонов ищут шаблоны в подкаталоге templates установленных приложений. Это общее имя сохранено для обратной совместимости.
DjangoTemplates движки принимают следующие OPTIONS:
-
'autoescape': логическое значение, которое управляет включением автоэскейпинга HTML.По умолчанию равно
True.Предупреждение
Устанавливайте это значение только в
False, если вы используете шаблоны, не являющиеся HTML! -
'context_processors': список пунктированных путей Python к вызовам, которые используются для заполнения контекста при отрисовке шаблона с запросом. Эти вызовы принимают объект запроса в качестве аргумента и возвращаютdictэлементов, которые будут объединены в контекст.По умолчанию пустой список.
См.
RequestContextдля получения дополнительной информации. -
'debug': логическое значение, которое включает/отключает режим отладки шаблонов. Если он равенTrue, страница ошибок отобразит подробный отчёт об исключении, возникшем во время отрисовки шаблона. Этот отчёт содержит соответствующий фрагмент шаблона с выделенной строкой.По умолчанию принимает значение настройки
DEBUG. -
'loaders': список пунктированных путей Python к классам загрузчиков шаблонов. Каждый класс загрузчика шаблонов знает, как импортировать шаблоны из определённого источника. Допускается использование кортежа вместо строки. Первый элемент кортежа должен содержать имя класса загрузчика, а последующие элементы передаются классу загрузчика при инициализации.Значение по умолчанию зависит от значений
DIRSиAPP_DIRS.См. Типы загрузчиков для получения подробностей.
-
'string_if_invalid': строковое представление вывода, которое система шаблонов должна использовать для недопустимых (например, неверно написанных) переменных.По умолчанию пустая строка.
См. Как обрабатываются недопустимые переменные для получения подробностей.
-
'file_charset': кодировка символов, используемая для чтения файлов шаблонов на диске.По умолчанию
'utf-8'. -
'libraries': словарь меток и пунктированных путей Python к модулям тегов шаблонов для регистрации в движке шаблонов. Это можно использовать для добавления новых библиотек или предоставления альтернативных меток для существующих. Например:OPTIONS = { "libraries": { "myapp_tags": "path.to.myapp.tags", "admin.urls": "django.contrib.admin.templatetags.admin_urls", }, }Библиотеки могут быть загружены, передав соответствующий ключ словаря тегу
{% load %}. -
'builtins': список пунктированных путей Python к модулям тегов шаблонов для добавления в встроенные. Например:OPTIONS = { "builtins": ["myapp.builtins"], }Теги и фильтры из встроенных библиотек могут быть использованы без предварительного вызова тега
{% load %}.
-
class Jinja2[source]
Требуется установка Jinja2:
$ python -m pip install Jinja2
...\> py -m pip install Jinja2
Установите BACKEND на 'django.template.backends.jinja2.Jinja2', чтобы настроить движок Jinja2.
Когда APP_DIRS имеет значение True, движки шаблонов ищут шаблоны в подкаталоге jinja2 установленных приложений.
Самый важный элемент в OPTIONS — 'environment'. Это пунктированный путь Python к вызываемому объекту, возвращающему среду Jinja2. По умолчанию это 'jinja2.Environment'. Django вызывает этот вызываемый объект и передаёт другие опции в качестве ключевых аргументов. Более того, Django добавляет значения по умолчанию, отличающиеся от значений Jinja2 для нескольких опций:
-
'autoescape':True -
'loader': загрузчик, настроенный дляDIRSиAPP_DIRS -
'auto_reload':settings.DEBUG -
'undefined':DebugUndefined if settings.DEBUG else Undefined
Jinja2 движки также принимают следующие OPTIONS:
-
'context_processors': список пунктированных путей Python к вызываемым объектам, используемым для заполнения контекста при отрисовке шаблона с запросом. Эти вызываемые объекты принимают объект запроса в качестве аргумента и возвращаютdictэлементов, которые будут объединены в контекст.По умолчанию пустой список.
Использование обработчиков контекста с шаблонами Jinja2 не рекомендуется.
Обработчики контекста полезны с шаблонами Django, потому что шаблоны Django не поддерживают вызов функций с аргументами. Поскольку Jinja2 не имеет такого ограничения, рекомендуется поместить функцию, которую вы бы использовали как обработчик контекста, в глобальные переменные, доступные для шаблона, используя
jinja2.Environment, как описано ниже. Затем вы можете вызвать эту функцию в шаблоне:{{ function(request) }}Некоторые обработчики контекста шаблонов Django возвращают фиксированное значение. Для шаблонов Jinja2 такой уровень косвенности не нужен, так как вы можете добавлять константы непосредственно в
jinja2.Environment.Исходный случай использования добавления обработчиков контекста для шаблонов Jinja2 включал:
- Выполнение дорогостоящего вычисления, зависящего от запроса.
- Необходимость результата во всех шаблонах.
- Использование результата несколько раз в каждом шаблоне.
Если не все эти условия выполнены, передача функции в шаблон больше соответствует дизайну Jinja2.
Конфигурация по умолчанию намеренно сведена к минимуму. Если шаблон отрисовывается с запросом (например, при использовании render()), бэкенд Jinja2 добавляет в контекст глобальные переменные request, csrf_input и csrf_token. Помимо этого, этот бэкенд не создаёт среду в стиле Django. Он не знает о фильтрах и тегах Django. Чтобы использовать специфичные для Django API, вы должны их настроить в среде.
Например, вы можете создать myproject/jinja2.py с этим содержимым:
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update(
{
"static": static,
"url": reverse,
}
)
return env
и установить опцию 'environment' на 'myproject.jinja2.environment'.
Затем вы можете использовать следующие конструкции в шаблонах Jinja2:
<img src="{{ static('path/to/company-logo.png') }}" alt="Company Logo">
<a href="{{ url('admin:index') }}">Administration</a>
Концепции тегов и фильтров существуют как в языке шаблонов Django, так и в Jinja2, но используются по-разному. Поскольку Jinja2 поддерживает передачу аргументов в вызываемые объекты в шаблонах, многие функции, требующие тега или фильтра в шаблонах Django, могут быть реализованы вызовом функции в шаблонах Jinja2, как показано в примере выше. Глобальное пространство имён Jinja2 устраняет необходимость в обработчиках контекста шаблонов Django. Язык шаблонов Django не имеет эквивалента тестам Jinja2.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.2/topics/templates/