Язык шаблонов Django: для программистов на Python
В этом документе система шаблонов Django рассматривается с технической точки зрения: как она работает и как её расширять. Если вам нужна справка по синтаксису языка, см. Язык шаблонов Django.
Предполагается, что вы понимаете, что такое шаблоны, контексты, переменные, теги и рендеринг. Если вы не знакомы с этими понятиями, начните с введения в язык шаблонов Django.
Обзор
Использование системы шаблонов в Python состоит из трёх шагов:
- Настройте
Engine. - Скомпилируйте код шаблона в
Template. - Выполните рендеринг шаблона с помощью
Context.
В проектах Django для каждого из этих шагов обычно используются высокоуровневые API, не зависящие от бэкенда, а не низкоуровневые API системы шаблонов:
- Для каждого бэкенда
DjangoTemplatesв параметреTEMPLATESDjango создаёт экземплярEngine.DjangoTemplatesоборачиваетEngineи адаптирует его к общему API бэкенда шаблонов. - Модуль
django.template.loaderпредоставляет такие функции, какget_template(), для загрузки шаблонов. Они возвращаютdjango.template.backends.django.Template, который оборачивает собственноdjango.template.Template. - У
Template, полученного на предыдущем шаге, есть методrender(), который преобразует контекст и, возможно, запрос вContextи делегирует рендеринг базовомуTemplate.
Настройка движка
Если вы используете бэкенд DjangoTemplates, вероятно, это не та документация, которая вам нужна. Экземпляр класса Engine, описанного ниже, доступен через атрибут engine этого бэкенда, а значения атрибутов по умолчанию, упомянутые ниже, переопределяются значениями, переданными в DjangoTemplates.
-
class Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None, autoescape=True)[исходный код] -
При создании экземпляра
Engineвсе аргументы необходимо передавать как именованные:-
dirs— список каталогов, в которых движок должен искать исходные файлы шаблонов. Используется для настройкиfilesystem.Loader.По умолчанию используется пустой список.
-
app_dirsвлияет только на значение по умолчанию дляloaders. См. ниже.По умолчанию используется
False. -
autoescapeуправляет включением автоматического экранирования HTML.По умолчанию используется
True.Предупреждение
Устанавливайте значение
Falseтолько при рендеринге шаблонов не в формате HTML! -
context_processors— список путей Python с точечной нотацией к вызываемым объектам, которые используются для заполнения контекста при рендеринге шаблона с запросом. Эти объекты принимают объект запроса в качестве аргумента и возвращаютdictэлементов, которые добавляются в контекст.По умолчанию используется пустой список.
Дополнительные сведения см. в разделе
RequestContext. -
debug— логическое значение, включающее или отключающее режим отладки шаблонов. Если оно равноTrue, движок шаблонов будет сохранять дополнительные отладочные сведения, которые можно использовать для отображения подробного отчёта о любом исключении, возникшем во время рендеринга шаблона.По умолчанию используется
False. -
loaders— список классов загрузчиков шаблонов, указанных в виде строк. Каждый классLoaderзнает, как загружать шаблоны из определённого источника. Вместо строки можно указать кортеж. Первым элементом кортежа должно быть имя классаLoader, остальные элементы передаются классуLoaderпри инициализации.По умолчанию используется список, содержащий:
'django.template.loaders.filesystem.Loader'-
'django.template.loaders.app_directories.Loader'тогда и только тогда, когдаapp_dirsравноTrue.
Затем эти загрузчики оборачиваются в
django.template.loaders.cached.Loader.Подробности см. в разделе Типы загрузчиков.
-
string_if_invalid— строка, которую система шаблонов должна выводить для недопустимых (например, содержащих опечатки) переменных.По умолчанию используется пустая строка.
Подробности см. в разделе Обработка недопустимых переменных.
-
file_charset— кодировка для чтения файлов шаблонов с диска.По умолчанию используется
'utf-8'. -
'libraries': словарь меток и путей Python с точечной нотацией к модулям тегов шаблонов, которые нужно зарегистрировать в движке шаблонов. Он используется для добавления новых библиотек или назначения альтернативных меток существующим. Например:Engine( libraries={ "myapp_tags": "path.to.myapp.tags", "admin.urls": "django.contrib.admin.templatetags.admin_urls", }, )Библиотеки можно загрузить, передав соответствующий ключ словаря тегу
{% load %}. -
'builtins': список путей Python с точечной нотацией к модулям тегов шаблонов, которые нужно добавить во встроенные библиотеки. Например:Engine( builtins=["myapp.builtins"], )Теги и фильтры из встроенных библиотек можно использовать без предварительного вызова тега
{% load %}.
-
-
static Engine.get_default()[исходный код] -
Возвращает базовый
Engineиз первого настроенного движкаDjangoTemplates. Если движки не настроены, возбуждаетImproperlyConfigured.Этот метод необходим для сохранения API, которые используют глобально доступный неявно настроенный движок. Настоятельно не рекомендуется применять его для других целей.
-
Engine.from_string(template_code)[исходный код] -
Компилирует переданный код шаблона и возвращает объект
Template.
-
Engine.get_template(template_name)[исходный код] -
Загружает шаблон с указанным именем, компилирует его и возвращает объект
Template.
-
Engine.select_template(template_name_list)[исходный код] -
Работает как
get_template(), но принимает список имён и возвращает первый найденный шаблон.
Загрузка шаблона
Рекомендуемый способ создать Template — вызвать фабричные методы Engine: get_template(), select_template() и from_string().
В проекте Django, где параметр TEMPLATES определяет движок DjangoTemplates, можно создать экземпляр Template напрямую. Если определено несколько движков DjangoTemplates, будет использоваться первый.
-
class Template[исходный код] -
Этот класс находится в
django.template.Template. Конструктор принимает один аргумент — исходный код шаблона:from django.template import Template template = Template("My name is {{ my_name }}.")
Как это устроено
Система разбирает исходный код шаблона только один раз — при создании объекта Template. После этого он хранится внутри в виде древовидной структуры для повышения производительности.
Сам разбор также выполняется довольно быстро. Большая часть разбора происходит за один вызов одного короткого регулярного выражения.
Рендеринг контекста
После компиляции объекта Template с его помощью можно выполнить рендеринг контекста. Один и тот же шаблон можно повторно использовать для рендеринга с разными контекстами.
-
class Context(dict_=None, autoescape=True, use_l10n=None, use_tz=None)[исходный код] -
Конструктор
django.template.Contextпринимает необязательный аргумент — словарь, сопоставляющий имена переменных с их значениями.Также можно указать три необязательных именованных аргумента:
-
autoescapeуправляет включением автоматического экранирования HTML.По умолчанию используется
True.Предупреждение
Устанавливайте значение
Falseтолько при рендеринге шаблонов не в формате HTML! -
use_l10nпереопределяет настройку локализации значений по умолчанию. Если задать значениеTrue, числа и даты будут форматироваться с учётом локали.По умолчанию используется
None.Подробности см. в разделе Управление локализацией в шаблонах.
-
use_tzпереопределяет настройку преобразования дат в местное время при рендеринге шаблона. Если задать значениеTrue, все даты будут отображаться в местном часовом поясе. Эта настройка имеет приоритет надUSE_TZ.По умолчанию используется
None.Подробности см. в разделе Вывод с учётом часового пояса в шаблонах.
Пример использования см. ниже в разделе Работа с объектами Context.
-
-
Template.render(context)[исходный код] -
Вызовите метод
render()объектаTemplate, передав емуContext, чтобы «заполнить» шаблон:>>> from django.template import Context, Template >>> template = Template("My name is {{ my_name }}.") >>> context = Context({"my_name": "Adrian"}) >>> template.render(context) "My name is Adrian." >>> context = Context({"my_name": "Dolores"}) >>> template.render(context) "My name is Dolores."
Переменные и поиск
Имена переменных должны состоять из букв (A–Z), цифр (0–9), символов подчёркивания (но не начинаться с подчёркивания) или точек.
Точки имеют особое значение при рендеринге шаблонов. Точка в имени переменной обозначает поиск. В частности, когда система шаблонов встречает точку в имени переменной, она пытается выполнить следующие виды поиска в указанном порядке:
- Поиск в словаре. Пример:
foo["bar"] - Поиск атрибута. Пример:
foo.bar - Поиск по индексу списка. Пример:
foo[bar]
Обратите внимание: «bar» в выражении шаблона, например {{ foo.bar }}, будет интерпретировано как строковый литерал, а не как значение переменной «bar», даже если такая переменная есть в контексте шаблона.
Система шаблонов использует первый подходящий тип поиска. Логика работает по принципу короткого замыкания. Вот несколько примеров:
>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."
>>> class PersonClass:
... pass
...
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."
>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."
Если какая-либо часть переменной является вызываемым объектом, система шаблонов попытается его вызвать. Пример:
>>> class PersonClass2:
... def name(self):
... return "Samantha"
...
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."
Обработка вызываемых переменных немного сложнее, чем обработка переменных, для которых нужен только обычный поиск. Следует учитывать несколько моментов:
-
Если при вызове переменной возникает исключение, оно будет передано дальше, если только у исключения нет атрибута
silent_variable_failureсо значениемTrue. Если у исключения есть атрибутsilent_variable_failureсо значениемTrue, переменная будет отображена как значение параметра конфигурацииstring_if_invalidдвижка (по умолчанию — пустая строка). Пример:>>> t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: ... def first_name(self): ... raise AssertionError("foo") ... >>> p = PersonClass3() >>> t.render(Context({"person": p})) Traceback (most recent call last): ... AssertionError: foo >>> class SilentAssertionError(Exception): ... silent_variable_failure = True ... >>> class PersonClass4: ... def first_name(self): ... raise SilentAssertionError ... >>> p = PersonClass4() >>> t.render(Context({"person": p})) "My name is ."Обратите внимание:
django.core.exceptions.ObjectDoesNotExist, базовый класс всех исключенийDoesNotExistAPI базы данных Django, содержитsilent_variable_failure = True. Поэтому при использовании шаблонов Django с объектами моделей Django любые исключенияDoesNotExistбудут игнорироваться без уведомления. - Переменную можно вызвать, только если у неё нет обязательных аргументов. В противном случае система вернёт значение параметра
string_if_invalidдвижка.
-
Вызов некоторых переменных может иметь побочные эффекты, поэтому разрешать системе шаблонов обращаться к ним было бы неразумно или небезопасно.
Хороший пример — метод
delete()каждого объекта модели Django. Система шаблонов не должна позволять выполнять такие действия:I will now delete this valuable data. {{ data.delete }}Чтобы этого избежать, задайте вызываемой переменной атрибут
alters_data. Система шаблонов не будет вызывать переменную, если у неё заданalters_data=True, и вместо этого безусловно заменит переменную наstring_if_invalid. Динамически созданные методыdelete()иsave()объектов моделей Django автоматически получаютalters_data=True. Пример:def sensitive_function(self): self.database_record.delete() sensitive_function.alters_data = True - Иногда эту функцию нужно отключить по другим причинам и указать системе шаблонов всегда оставлять переменную невызванной. Для этого задайте вызываемому объекту атрибут
do_not_call_in_templatesсо значениемTrue. Тогда система шаблонов будет считать переменную невызываемой (например, это позволит обращаться к атрибутам вызываемого объекта).
Обработка недопустимых переменных
Как правило, если переменная не существует, система шаблонов подставляет значение параметра конфигурации string_if_invalid движка, которому по умолчанию присвоено значение '' (пустая строка).
Фильтры, применённые к недопустимой переменной, будут выполняться, только если string_if_invalid установлено в '' (пустую строку). Если для string_if_invalid задано любое другое значение, фильтры переменных будут игнорироваться.
Для тегов шаблонов if, for и regroup это поведение немного отличается. Если одному из этих тегов шаблонов передана недопустимая переменная, она будет интерпретирована как None. К недопустимым переменным внутри этих тегов шаблонов фильтры применяются всегда.
Если string_if_invalid содержит '%s', маркер формата будет заменён именем недопустимой переменной.
Только для отладки!
Хотя string_if_invalid может быть полезным инструментом отладки, не рекомендуется включать его по умолчанию при разработке.
Многие шаблоны, в том числе некоторые шаблоны Django, полагаются на то, что система шаблонов не сообщает об отсутствующих переменных. Если присвоить string_if_invalid значение, отличное от '', при рендеринге таких шаблонов и сайтов возникнут проблемы.
Как правило, string_if_invalid следует включать только для отладки конкретной проблемы с шаблоном, а после завершения отладки отключать.
Встроенные переменные
Каждый контекст содержит True, False и None. Как и следовало ожидать, эти переменные соответствуют объектам Python с такими же именами.
Ограничения строковых литералов
В языке шаблонов Django нет способа экранировать символы, используемые в его собственном синтаксисе. Например, если нужно вывести такие последовательности символов, как {% и %}, необходимо использовать тег templatetag.
Аналогичная проблема возникает, если вы хотите включить эти последовательности в аргументы фильтров или тегов шаблонов. Например, при разборе блочного тега анализатор шаблонов Django ищет первое вхождение %} после {%. Поэтому использовать "%}" в качестве строкового литерала нельзя. Например, для следующих выражений будет вызвано исключение TemplateSyntaxError:
{% include "template.html" tvar="Some string literal with %} in it." %}
{% with tvar="Some string literal with %} in it." %}{% endwith %}
Та же проблема возникает при использовании зарезервированной последовательности в аргументах фильтра:
{{ some.variable|default:"}}" }}
Если вам нужно использовать строки с такими последовательностями, сохраните их в переменных шаблона или воспользуйтесь пользовательским тегом шаблона либо фильтром, чтобы обойти это ограничение.
Работа с объектами Context
В большинстве случаев вы создадите объекты Context, передав полностью заполненный словарь в Context(). Но после создания объекта Context в него также можно добавлять и удалять элементы, используя стандартный синтаксис словарей:
>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c["foo"]
'bar'
>>> del c["foo"]
>>> c["foo"]
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c["newvariable"] = "hello"
>>> c["newvariable"]
'hello'
-
Context.get(key, otherwise=None) -
Возвращает значение для
key, еслиkeyнаходится в контексте, иначе возвращаетotherwise.
-
Context.setdefault(key, default=None) -
Если
keyнаходится в контексте, возвращает его значение. В противном случае добавляетkeyсо значениемdefaultи возвращаетdefault.
-
Context.pop()
-
Context.push()
-
exception ContextPopException[исходный код]
Объект Context представляет собой стек. То есть в него можно push() и pop(). Если вызвать pop() слишком много раз, будет сгенерировано исключение django.template.ContextPopException:
>>> c = Context()
>>> c["foo"] = "first level"
>>> c.push()
{}
>>> c["foo"] = "second level"
>>> c["foo"]
'second level'
>>> c.pop()
{'foo': 'second level'}
>>> c["foo"]
'first level'
>>> c["foo"] = "overwritten"
>>> c["foo"]
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
ContextPopException
Вы также можете использовать push() в качестве менеджера контекста, чтобы гарантировать вызов соответствующего pop().
>>> c = Context() >>> c["foo"] = "first level" >>> with c.push(): ... c["foo"] = "second level" ... c["foo"] ... 'second level' >>> c["foo"] 'first level'
Все аргументы, переданные в push(), будут переданы конструктору dict, используемому для создания нового уровня контекста.
>>> c = Context() >>> c["foo"] = "first level" >>> with c.push(foo="second level"): ... c["foo"] ... 'second level' >>> c["foo"] 'first level'
-
Context.update(other_dict)[исходный код]
Помимо push() и pop(), объект Context также определяет метод update(). Он работает как push(), но принимает словарь в качестве аргумента и помещает этот словарь в стек вместо пустого.
>>> c = Context()
>>> c["foo"] = "first level"
>>> c.update({"foo": "updated"})
{'foo': 'updated'}
>>> c["foo"]
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c["foo"]
'first level'
Как и push(), update() можно использовать в качестве менеджера контекста, чтобы гарантировать вызов соответствующего pop().
>>> c = Context()
>>> c["foo"] = "first level"
>>> with c.update({"foo": "second level"}):
... c["foo"]
...
'second level'
>>> c["foo"]
'first level'
Использование Context в качестве стека удобно при создании некоторых пользовательских тегов шаблонов.
-
Context.flatten()
С помощью метода flatten() можно получить весь стек Context в виде одного словаря, включая встроенные переменные.
>>> c = Context()
>>> c["foo"] = "first level"
>>> c.update({"bar": "second level"})
{'bar': 'second level'}
>>> c.flatten()
{'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}
Метод flatten() также используется внутри системы для сравнения объектов Context.
>>> c1 = Context()
>>> c1["foo"] = "first level"
>>> c1["bar"] = "second level"
>>> c2 = Context()
>>> c2.update({"bar": "second level", "foo": "first level"})
{'foo': 'first level', 'bar': 'second level'}
>>> c1 == c2
True
Результат flatten() может быть полезен в модульных тестах для сравнения Context с dict:
class ContextTest(unittest.TestCase):
def test_against_dictionary(self):
c1 = Context()
c1["update"] = "value"
self.assertEqual(
c1.flatten(),
{
"True": True,
"None": None,
"False": False,
"update": "value",
},
)
Использование RequestContext
-
class RequestContext(request, dict_=None, processors=None, use_l10n=None, use_tz=None, autoescape=True)[исходный код]
Django предоставляет специальный класс Context — django.template.RequestContext, который немного отличается от обычного django.template.Context. Первое отличие заключается в том, что он принимает HttpRequest в качестве первого аргумента. Например:
c = RequestContext(
request,
{
"foo": "bar",
},
)
Второе отличие заключается в том, что он автоматически заполняет контекст несколькими переменными в соответствии с параметром конфигурации context_processors движка.
Параметр context_processors — это список вызываемых объектов, называемых процессорами контекста. Они принимают объект запроса в качестве аргумента и возвращают словарь элементов, которые объединяются с контекстом. В файле настроек, создаваемом по умолчанию, движок шаблонов содержит следующие процессоры контекста:
[
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
]
Кроме того, RequestContext всегда включает 'django.template.context_processors.csrf'. Это процессор контекста, связанный с безопасностью и необходимый административному приложению и другим приложениям contrib. На случай случайной неправильной настройки он намеренно задан жестко и не может быть отключен в параметре context_processors.
Каждый процессор применяется по порядку. Это означает, что если один процессор добавляет переменную в контекст, а второй процессор добавляет переменную с таким же именем, второй заменит первый. Процессоры по умолчанию описаны ниже.
Когда применяются процессоры контекста
Процессоры контекста применяются поверх данных контекста. Это означает, что процессор контекста может переопределить переменные, которые вы передали в Context или RequestContext. Поэтому избегайте имен переменных, совпадающих с именами переменных, предоставляемых процессорами контекста.
Если данные контекста должны иметь приоритет над процессорами контекста, используйте следующий шаблон:
from django.template import RequestContext
request_context = RequestContext(request)
request_context.push({"my_name": "Adrian"})
Django делает это, чтобы данные контекста могли переопределять процессоры контекста в таких API, как render() и TemplateResponse.
Также можно передать RequestContext список дополнительных процессоров, используя необязательный третий позиционный аргумент processors. В этом примере экземпляр RequestContext получает переменную ip_address:
from django.http import HttpResponse
from django.template import RequestContext, Template
def ip_address_processor(request):
return {"ip_address": request.META["REMOTE_ADDR"]}
def client_ip_view(request):
template = Template("{{ title }}: {{ ip_address }}")
context = RequestContext(
request,
{
"title": "Your IP Address",
},
[ip_address_processor],
)
return HttpResponse(template.render(context))
Встроенные процессоры контекста шаблонов
Ниже описано, что делает каждый из встроенных процессоров:
django.contrib.auth.context_processors.auth
-
auth(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать следующие переменные:
-
user— экземплярauth.User, представляющий текущего вошедшего в систему пользователя (или экземплярAnonymousUser, если клиент не вошел в систему). -
perms— экземплярdjango.contrib.auth.context_processors.PermWrapper, представляющий разрешения, которыми обладает текущий вошедший в систему пользователь.
django.template.context_processors.debug
-
debug(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать следующие две переменные — но только если параметр DEBUG установлен в True, а IP-адрес запроса (request.META['REMOTE_ADDR']) указан в параметре INTERNAL_IPS:
-
debug—True. Эту переменную можно использовать в шаблонах, чтобы проверить, включен ли режимDEBUG. -
sql_queries— список словарей{'sql': ..., 'time': ...}, представляющих все SQL-запросы, выполненные к этому моменту во время обработки запроса, и время их выполнения. Список упорядочен сначала по псевдониму базы данных, а затем по запросу. Он формируется лениво при обращении к нему.
django.template.context_processors.i18n
-
i18n(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать следующие переменные:
-
LANGUAGES— значение параметраLANGUAGES. -
LANGUAGE_BIDI—True, если текущий язык пишется справа налево, например иврит или арабский.False, если язык пишется слева направо, например английский, французский или немецкий. -
LANGUAGE_CODE—request.LANGUAGE_CODE, если он задан. В противном случае — значение параметраLANGUAGE_CODE.
Теги шаблонов, формирующие те же значения, описаны в разделе теги шаблонов i18n.
django.template.context_processors.media
Если этот процессор включен, каждый RequestContext будет содержать переменную MEDIA_URL со значением параметра MEDIA_URL.
django.template.context_processors.static
-
static(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать переменную STATIC_URL со значением параметра STATIC_URL.
django.template.context_processors.csrf
Этот процессор добавляет токен, необходимый тегу шаблона csrf_token для защиты от подделки межсайтовых запросов.
django.template.context_processors.csp
-
csp(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать переменную csp_nonce — криптографически безопасный nonce, генерируемый отдельно для каждого запроса и пригодный для использования с политикой безопасности содержимого. Подробности см. в разделе использование nonce в CSP.
django.template.context_processors.request
Если этот процессор включен, каждый RequestContext будет содержать переменную request, представляющую текущий объект HttpRequest.
django.template.context_processors.tz
-
tz(request)[исходный код]
Если этот процессор включен, каждый RequestContext будет содержать переменную TIME_ZONE с названием текущего активного часового пояса.
django.contrib.messages.context_processors.messages
Если этот процессор включен, каждый RequestContext будет содержать следующие две переменные:
-
messages— список сообщений (в виде строк), добавленных через фреймворк сообщений. -
DEFAULT_MESSAGE_LEVELS— соответствие названий уровней сообщений их числовым значениям.
Создание собственных процессоров контекста
У процессора контекста простой интерфейс: это функция Python, принимающая один аргумент — объект HttpRequest — и возвращающая словарь, который добавляется в контекст шаблона.
Например, чтобы добавить параметр DEFAULT_FROM_EMAIL во все контексты:
from django.conf import settings
def from_email(request):
return {
"DEFAULT_FROM_EMAIL": settings.DEFAULT_FROM_EMAIL,
}
Пользовательские процессоры контекста можно размещать в любой части вашей кодовой базы. Django важно лишь, чтобы на пользовательские процессоры контекста ссылался параметр 'context_processors' в настройке TEMPLATES или аргумент context_processors класса Engine, если вы используете его напрямую.
Загрузка шаблонов
Как правило, шаблоны хранятся в файлах в файловой системе, а не создаются напрямую с помощью низкоуровневого API Template. Сохраняйте шаблоны в каталоге, называемом каталогом шаблонов.
Django ищет каталоги шаблонов в нескольких местах, в зависимости от настроек загрузки шаблонов (см. раздел «Типы загрузчиков» ниже). Самый простой способ указать каталоги шаблонов — использовать параметр DIRS.
Параметр DIRS
Укажите Django каталоги шаблонов с помощью параметра DIRS в настройке TEMPLATES в файле настроек или аргумента dirs класса Engine. Здесь должен быть список строк с полными путями к каталогам шаблонов:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/home/html/templates/lawrence.com",
"/home/html/templates/default",
],
},
]
Шаблоны можно размещать в любом месте, если веб-сервер имеет доступ на чтение к каталогам и шаблонам. Файлы могут иметь любое расширение, например .html или .txt, либо не иметь расширения вовсе.
Обратите внимание: пути следует записывать с использованием прямых слешей в стиле Unix, даже в Windows.
Типы загрузчиков
По умолчанию Django использует загрузчик шаблонов на основе файловой системы, но в Django есть и другие загрузчики, умеющие загружать шаблоны из других источников.
Некоторые из этих загрузчиков по умолчанию отключены, но их можно включить, добавив параметр 'loaders' в бэкенд DjangoTemplates в настройке TEMPLATES или передав аргумент loaders классу Engine. Параметр loaders должен содержать список строк или кортежей, каждый из которых задает класс загрузчика шаблонов. В Django предусмотрены следующие загрузчики шаблонов:
django.template.loaders.filesystem.Loader
-
class filesystem.Loader -
Загружает шаблоны из файловой системы в соответствии с параметром
DIRS.Этот загрузчик включен по умолчанию. Однако он не найдет ни одного шаблона, пока вы не зададите для
DIRSнепустой список:TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], } ]Также можно переопределить
'DIRS'и указать конкретные каталоги для определенного загрузчика файловой системы:TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "OPTIONS": { "loaders": [ ( "django.template.loaders.filesystem.Loader", [BASE_DIR / "templates"], ), ], }, } ]
django.template.loaders.app_directories.Loader
-
class app_directories.Loader -
Загружает шаблоны из приложений Django в файловой системе. Для каждого приложения в
INSTALLED_APPSзагрузчик ищет подкаталогtemplates. Если каталог существует, Django ищет в нем шаблоны.Это позволяет хранить шаблоны вместе с отдельными приложениями. Такой подход также упрощает распространение приложений Django с шаблонами по умолчанию.
Например, для такой настройки:
INSTALLED_APPS = ["myproject.polls", "myproject.music"]
…
get_template('foo.html')будет искатьfoo.htmlв следующих каталогах, в указанном порядке:/path/to/myproject/polls/templates//path/to/myproject/music/templates/
…и использует первый найденный файл.
Порядок элементов в
INSTALLED_APPSимеет значение! Например, если вы хотите настроить административный интерфейс Django, можно переопределить стандартный шаблонadmin/base_site.htmlизdjango.contrib.adminсобственным шаблономadmin/base_site.htmlвmyproject.polls. В этом случае необходимо убедиться, чтоmyproject.pollsнаходится в списке раньшеdjango.contrib.adminвINSTALLED_APPS. Иначе сначала будет загружен шаблонdjango.contrib.admin, а ваш шаблон будет проигнорирован.Обратите внимание: при первом запуске загрузчик выполняет оптимизацию — кэширует список пакетов
INSTALLED_APPS, содержащих подкаталогtemplates.Включить этот загрузчик можно, установив для
APP_DIRSзначениеTrue:TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "APP_DIRS": True, } ]
django.template.loaders.cached.Loader
-
class cached.Loader -
Система шаблонов Django работает достаточно быстро, однако, если шаблоны приходится читать и компилировать при каждом отображении, связанные с этим затраты могут накапливаться.
Для настройки кэширующего загрузчика шаблонов укажите список других загрузчиков, которые он должен оборачивать. Обернутые загрузчики используются для поиска неизвестных шаблонов при первом обращении к ним. Затем кэширующий загрузчик сохраняет скомпилированный
Templateв памяти. При последующих запросах на загрузку того же шаблона возвращается кэшированный экземплярTemplate.Этот загрузчик включается автоматически, если параметр
OPTIONS['loaders']не указан.Кэширование шаблонов можно настроить вручную с помощью пользовательских загрузчиков, например так:
TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "templates"], "OPTIONS": { "loaders": [ ( "django.template.loaders.cached.Loader", [ "django.template.loaders.filesystem.Loader", "django.template.loaders.app_directories.Loader", "path.to.custom.Loader", ], ), ], }, } ]Примечание
Все встроенные теги шаблонов Django безопасно использовать с кэширующим загрузчиком. Однако, если вы используете пользовательские теги шаблонов из сторонних пакетов или созданные вами самостоятельно, убедитесь, что реализация
Nodeкаждого тега является потокобезопасной. Дополнительные сведения см. в разделе обеспечение потокобезопасности тегов шаблонов.
django.template.loaders.locmem.Loader
-
class locmem.Loader -
Загружает шаблоны из словаря Python. Это полезно для тестирования.
Этот загрузчик принимает словарь шаблонов в качестве первого аргумента:
TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "OPTIONS": { "loaders": [ ( "django.template.loaders.locmem.Loader", { "index.html": "content here", }, ), ], }, } ]По умолчанию этот загрузчик отключен.
Django использует загрузчики шаблонов в порядке, заданном параметром 'loaders', пока один из них не найдет совпадение.
Пользовательские загрузчики
С помощью пользовательских загрузчиков можно загружать шаблоны из дополнительных источников. Пользовательские классы Loader должны наследоваться от django.template.loaders.base.Loader и определять методы get_contents() и get_template_sources().
Методы загрузчика
-
class Loader[исходный код] -
Загружает шаблоны из указанного источника, например из файловой системы или базы данных.
-
get_template_sources(template_name)[исходный код] -
Метод принимает
template_nameи возвращает экземплярыOriginдля каждого возможного источника.Например, загрузчик файловой системы может получить
'index.html'в качестве аргументаtemplate_name. Этот метод возвращает источники для полного путиindex.htmlв каждом каталоге шаблонов, который проверяет загрузчик.Методу не нужно проверять, существует ли шаблон по указанному пути, но он должен убедиться, что путь допустим. Например, загрузчик файловой системы проверяет, что путь находится внутри допустимого каталога шаблонов.
-
get_contents(origin) -
Возвращает содержимое шаблона для заданного экземпляра
Origin.Загрузчик файловой системы читает содержимое из файловой системы, а загрузчик базы данных — из базы данных. Если подходящий шаблон не существует, необходимо сгенерировать исключение
TemplateDoesNotExist.
-
get_template(template_name, skip=None)[исходный код] -
Возвращает объект
Templateдля заданногоtemplate_name, перебирая результатыget_template_sources()и вызываяget_contents(). Возвращается первый подходящий шаблон. Если шаблон не найден, генерируется исключениеTemplateDoesNotExist.Необязательный аргумент
skip— это список источников, которые следует игнорировать при расширении шаблонов. Это позволяет шаблонам расширять другие шаблоны с таким же именем. Также аргумент используется для предотвращения ошибок рекурсии.Как правило, для создания пользовательских загрузчиков шаблонов достаточно определить методы
get_template_sources()иget_contents(). Обычно переопределятьget_template()не требуется.
-
Создание собственного загрузчика
Примеры можно найти в исходном коде встроенных загрузчиков Django.
Происхождение шаблона
Шаблоны имеют origin с атрибутами, зависящими от источника, из которого они загружены.
-
class Origin(name, template_name=None, loader=None)[исходный код] -
-
name -
Путь к шаблону, возвращаемый загрузчиком шаблонов. Для загрузчиков, считывающих данные из файловой системы, это полный путь к шаблону.
Если шаблон создаётся напрямую, а не через загрузчик шаблонов, это строковое значение
<unknown_source>.
-
template_name -
Относительный путь к шаблону, передаваемый загрузчику шаблонов.
Если шаблон создаётся напрямую, а не через загрузчик шаблонов, это
None.
-
loader -
Экземпляр загрузчика шаблонов, создавший этот
Origin.Если шаблон создаётся напрямую, а не через загрузчик шаблонов, это
None.django.template.loaders.cached.Loaderтребует, чтобы все обёрнутые им загрузчики задавали этот атрибут, обычно создавая экземплярOriginс помощьюloader=self.
-
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/ref/templates/api/