Шаблоны¶
Django - это веб-фреймворк, поэтому ему нужен удобный способ динамической генерации HTML. Самый распространенный подход основан на шаблонах. Шаблон содержит статические части желаемого вывода HTML, а также некоторый специальный синтаксис, описывающий, как будет вставлен динамический контент. Практический пример создания HTML-страниц с помощью шаблонов смотрите в Учебник, часть 3.
Проект Django можно настроить с одним или несколькими шаблонизаторами (или даже с нулем, если вы не используете шаблоны). Django предоставляет встроенные серверные модули для собственной системы шаблонов, творчески названной языком шаблонов Django (DTL), и для популярной альтернативы Jinja2. Серверные программы для других языков шаблонов могут быть доступны у третьих лиц. Вы также можете написать свой собственный бэкэнд, смотрите Пользовательский бэкэнд
Django определяет стандартный API для загрузки и рендеринга шаблонов независимо от серверной части. Загрузка состоит из поиска шаблона для данного идентификатора и его предварительной обработки, обычно компилируя его в представление в памяти. Рендеринг означает интерполяцию шаблона с помощью контекстных данных и возврат результирующей строки.
Язык шаблонов Django - это собственная система шаблонов Django. До Django 1.8 это была единственная доступная встроенная опция. Это хорошая библиотека шаблонов, даже несмотря на то, что она довольно самоуверенная и имеет несколько особенностей. Если у вас нет веских причин для выбора другой серверной части, вам следует использовать DTL, особенно если вы пишете подключаемое приложение и собираетесь распространять шаблоны. Приложения contrib Django, которые включают шаблоны, например django.contrib.admin, используют DTL.
По историческим причинам как общая поддержка шаблонов, так и реализация языка шаблонов Django находятся в пространстве имен django.template
.
Предупреждение
Система шаблонов небезопасна от ненадежных авторов шаблонов. Например, сайт не должен позволять своим пользователям предоставлять свои собственные шаблоны, поскольку авторы шаблонов могут выполнять такие действия, как выполнение XSS-атак и доступ к свойствам переменных шаблона, которые могут содержать конфиденциальную информацию.
Язык шаблонов Django¶
Синтаксис¶
Об этом разделе
Это обзор синтаксиса языка шаблонов Django. Подробнее смотрите справочник по синтаксису языка.
Шаблон Django - это текстовый документ или строка Python, размеченная с использованием языка шаблонов Django. Некоторые конструкции распознаются и интерпретируются механизмом шаблонов. Основные из них - переменные и теги.
Шаблон отображается с контекстом. Визуализация заменяет переменные их значениями, которые просматриваются в контексте, и выполняет теги. Все остальное выводится как есть.
Синтаксис языка шаблонов Django включает четыре конструкции.
Переменные¶
Переменная выводит значение из контекста, которое представляет собой dict-подобный объект, отображающий ключи к значениям.
Переменные заключаются в символы {{
и }}
, например:
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 }}
Если переменная преобразуется в вызываемую, система шаблонов вызовет ее без аргументов и будет использовать ее результат вместо вызываемого.
Тэги¶
Теги обеспечивают произвольную логику в процессе рендеринга.
Это определение заведомо расплывчатое. Например, тег может выводить контент, служить структурой управления, например. оператор «if» или цикл «for», захват содержимого из базы данных или даже разрешение доступа к другим тегам шаблона.
Теги заключаются в символы {%
и %}
, например:
{% csrf_token %}
Большинство тегов принимают аргументы:
{% cycle 'odd' 'even' %}
Для некоторых тегов требуются начальные и конечные теги:
{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}
Справочник по встроенным тегам, а также инструкции по написанию пользовательских тегов.
Фильтры¶
Фильтры преобразуют значения переменных и аргументов тегов.
Выглядят они так:
{{ 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
. Это список конфигураций, по одной для каждого двигателя. Значение по умолчанию пусто. Файл settings.py
, созданный командой 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)[исходный код]¶ Эта функция загружает шаблон с заданным именем и возвращает объект
Template
.Точный тип возвращаемого значения зависит от серверной части, загрузившей шаблон. У каждого бэкэнда есть свой класс
Template
.get_template()
пробует каждый механизм шаблонов по порядку, пока один из них не добьется успеха. Если шаблон не может быть найден, он вызываетTemplateDoesNotExist
. Если шаблон найден, но содержит недопустимый синтаксис, он вызываетTemplateSyntaxError
.То, как ищутся и загружаются шаблоны, зависит от серверной части и конфигурации каждого движка.
Если вы хотите ограничить поиск конкретным механизмом шаблонов, передайте параметр движка
NAME
в аргументеusing
.
-
select_template
(template_name_list, using=None)[исходный код]¶ select_template()
похож наget_template()
, за исключением того, что он принимает список имен шаблонов. Он пробует каждое имя по порядку и возвращает первый существующий шаблон.
Если загрузка шаблона не удалась, могут возникнуть следующие два исключения, определенные в django.template
:
-
exception
TemplateDoesNotExist
(msg, tried=None, backend=None, chain=None)[исходный код]¶ Это исключение возникает, когда не удается найти шаблон. Он принимает следующие необязательные аргументы для заполнения template postmortem на странице отладки:
backend
- Экземпляр серверной части шаблона, из которого возникло исключение.
tried
- Список источников, которые были опробованы при поиске шаблона. Он отформатирован как список кортежей, содержащих
(origin, status)
, гдеorigin
- это объект origin-like, аstatus
- строка с причиной, по которой шаблон не был найден. chain
- Список промежуточных исключений
TemplateDoesNotExist
, возникающих при попытке загрузить шаблон. Это используется такими функциями, какget_template()
, которые пытаются загрузить данный шаблон из нескольких движков.
-
exception
TemplateSyntaxError
(msg)[исходный код]¶ Это исключение возникает, когда шаблон был найден, но содержит ошибки.
Объекты Template
, возвращаемые get_template()
и select_template()
, должны предоставлять метод render()
со следующей сигнатурой:
-
Template.
render
(context=None, request=None)¶ Отображает этот шаблон в заданном контексте.
Если указан
context
, он должен бытьdict
. Если он не указан, движок отобразит шаблон с пустым контекстом.Если указан запрос, это должен быть
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'
engine)/home/html/default/story_detail.html
('django'
engine)/home/html/jinja2/story_detail.html
('jinja2'
engine)
Если вы вызовете select_template(['story_253_detail.html', 'story_detail.html'])
, вот что будет искать Django:
/home/html/example.com/story_253_detail.html
('django'
engine)/home/html/default/story_253_detail.html
('django'
engine)/home/html/jinja2/story_253_detail.html
('jinja2'
engine)/home/html/example.com/story_detail.html
('django'
engine)/home/html/default/story_detail.html
('django'
engine)/home/html/jinja2/story_detail.html
('jinja2'
engine)
Когда Django находит существующий шаблон, он перестает искать.
Подсказка
Вы можете использовать select_template()
для гибкой загрузки шаблона. Например, если вы написали новость и хотите, чтобы у некоторых записей были настраиваемые шаблоны, используйте что-то вроде select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])
. Это позволит вам использовать настраиваемый шаблон для отдельной истории с запасным шаблоном для историй, у которых нет настраиваемых шаблонов.
Можно - и предпочтительно - организовать шаблоны в подкаталогах внутри каждого каталога, содержащего шаблоны. Согласно соглашению, для каждого приложения Django создается подкаталог с подкаталогами внутри этих подкаталогов по мере необходимости.
Сделайте это для собственного здравомыслия. Хранение всех шаблонов в корневом уровне одного каталога становится беспорядочным.
Чтобы загрузить шаблон из подкаталога, используйте косую черту, например:
get_template('news/story_detail.html')
Используя тот же параметр TEMPLATES
, как указано выше, будет предпринята попытка загрузить следующие шаблоны:
/home/html/example.com/news/story_detail.html
('django'
engine)/home/html/default/news/story_detail.html
('django'
engine)/home/html/jinja2/news/story_detail.html
('jinja2'
engine)
Кроме того, чтобы сократить повторяющуюся природу загрузки и отрисовки шаблонов, Django предоставляет функцию быстрого доступа, которая автоматизирует процесс.
-
render_to_string
(template_name, context=None, request=None, using=None)[исходный код]¶ 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
, подходящий для возврата из представления.
Наконец, вы можете напрямую использовать настроенные движки:
Встроенные бэкенды¶
-
class
DjangoTemplates
[исходный код]¶
Установите BACKEND
на django.template.backends.django.DjangoTemplates
, чтобы настроить механизм шаблонов Django.
Когда APP_DIRS <TEMPLATES-APP_DIRS>`
имеет значение True
, движки DjangoTemplates
ищут шаблоны в подкаталоге templates
установленных приложений. Это общее имя было сохранено для обратной совместимости.
Механизмы DjangoTemplates
принимают следующее OPTIONS
:
autoescape
: логическое значение, которое определяет, включено ли автоматическое экранирование HTML.По умолчанию он равен
True
.Предупреждение
Устанавливайте значение
False
, только если вы рендерите не-HTML шаблоны!context_processors
“: список разделенных точками путей Python к вызываемым объектам, которые используются для заполнения контекста, когда шаблон отображается с запросом. Эти вызываемые объекты принимают объект запроса в качестве аргумента и возвращаютdict
элементов, которые необходимо объединить в контекст.По умолчанию это пустой список.
Дополнительную информацию см. в разделе
RequestContext
.'debug'
: логическое значение, которое включает/выключает режим отладки шаблона. Если установлено значениеTrue
, на необычной странице ошибок будет отображаться подробный отчет для любых исключений, возникающих во время отрисовки шаблона. Этот отчет содержит соответствующий фрагмент шаблона с выделенной соответствующей строкой.По умолчанию используется значение параметра
DEBUG
.'loaders'
: список разделенных точками путей Python к классам загрузчиков шаблонов. Каждый классLoader
знает, как импортировать шаблоны из определенного источника. При желании вместо строки можно использовать кортеж. Первым элементом в кортеже должно быть имя классаLoader
, а последующие элементы передаются вLoader
во время инициализации.Значение по умолчанию зависит от значений
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-путей модулей тегов шаблонов для добавления к built-ins. Например:OPTIONS={ 'builtins': ['myapp.builtins'], }
Теги и фильтры из встроенных библиотек можно использовать без предварительного вызова тега
{% load %}
.
-
class
Jinja2
[исходный код]¶
Требуется установка Jinja2:
$ python -m pip install Jinja2
...\> py -m pip install Jinja2
Установите BACKEND
на 'django.template.backends.jinja2.Jinja2'
для настройки движка Jinja2.
Когда APP_DIRS
имеет значение True
, движки Jinja2
ищут шаблоны в подкаталоге 'jinja2'
установленных приложений.
Самая важная запись в OPTIONS
- 'nvironment'
. Это пунктирный путь 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. Чтобы использовать API, специфичные для Django, вы должны настроить их в среде.
Например, вы можете создать 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 не имеет эквивалента тестов Jinja2.