Язык шаблонов 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.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)[source] -
При создании экземпляра
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"], ). Например:Engine( builtins=["myapp.builtins"], )Теги и фильтры из встроенных библиотек могут быть использованы без предварительного вызова тега
{% load %}.
-
-
static Engine.get_default()[source] -
Возвращает базовый
Engineиз первого настроенногоDjangoTemplatesдвижка. ВызываетImproperlyConfigured, если движки не настроены.Требуется для сохранения API, которые полагаются на глобально доступный, неявно настроенный движок. Любое другое использование настоятельно не рекомендуется.
-
Engine.from_string(template_code)[source] -
Компилирует предоставленный код шаблона и возвращает объект
Template.
-
Engine.get_template(template_name)[source] -
Загружает шаблон с заданным именем, компилирует его и возвращает объект
Template.
-
Engine.select_template(template_name_list)[source] -
Аналогично
get_template(), за исключением того, что принимает список имён и возвращает первый найденный шаблон.
Загрузка шаблона
Рекомендуемый способ создания Template заключается в вызове методов-фабрик Engine: get_template(), select_template() и from_string().
В проекте Django, где настройка TEMPLATES определяет движок DjangoTemplates, возможно непосредственное создание объекта Template. Если определено более одного движка DjangoTemplates, будет использован первый.
-
class Template[source] -
Этот класс находится по адресу
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)[source] -
Конструктор
django.template.Contextпринимает необязательный аргумент — словарь, сопоставляющий имена переменных с их значениями.Также можно указать три необязательных ключевых аргумента:
-
autoescapeуправляет включением автоматического экранирования HTML.По умолчанию
True.Предупреждение
Установите его в
Falseтолько если отображаете не HTML-шаблоны! -
use_l10nпереопределяет, будут ли значения по умолчанию локализованы. Если установлено вTrue, числа и даты будут отформатированы на основе локали.По умолчанию
None.Подробности см. в Управление локализациями в шаблонах.
-
use_tzпереопределяет, будут ли даты конвертированы в локальное время при отображении в шаблоне. Если установлено вTrue, все даты будут отображаться с использованием локальной временной зоны. Это имеет приоритет надUSE_TZ.По умолчанию
None.Подробности см. в Время по часовым поясам в шаблонах.
Примеры использования см. ниже в Работа с объектами Context.
-
-
Template.render(context)[source] -
Вызовите метод
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, переменная будет отображена как значение конфигурационного параметра движка %%%CODE_BLOCK_105%% (пустая строка по умолчанию). Пример:>>> 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, который является базовым классом для всех исключений API базы данных 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’s template parser ищет первое вхождение %} после {%. Это препятствует использованию "%}" в качестве строковой литералы. Например, ошибка 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[source]
Объект 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)[source]
Помимо 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)[source]
Django поставляется со специальным классом Context, django.template.RequestContext, который немного отличается от обычного django.template.Context. Первое отличие заключается в том, что он принимает HttpRequest в качестве первого аргумента. Например:
c = RequestContext(
request,
{
"foo": "bar",
},
)
Второе отличие заключается в том, что он автоматически заполняет контекст несколькими переменными в соответствии с настройкой context_processors движка.
Настройка context_processors представляет собой список вызываемых объектов — **обработчики контекста** — которые принимают объект запроса в качестве аргумента и возвращают словарь элементов, которые должны быть объединены в контекст. В файле настроек по умолчанию сгенерированном по умолчанию, стандартный движок шаблонов содержит следующие обработчики контекста:
[
"django.template.context_processors.debug",
"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)[source]
Если этот обработчик включен, каждый RequestContext будет содержать эти переменные:
-
user– Экземплярauth.User, представляющий текущего вошедшего пользователя (или экземплярAnonymousUserесли клиент не вошел). -
perms– Экземплярdjango.contrib.auth.context_processors.PermWrapper, представляющий разрешения текущего вошедшего пользователя.
django.template.context_processors.debug
-
debug(request)[source]
Если этот обработчик включен, каждый RequestContext будет содержать эти две переменные — но только если ваша настройка DEBUG установлена в True и IP-адрес запроса (request.META['REMOTE_ADDR']) находится в настройке INTERNAL_IPS:
-
debug–True. Вы можете использовать это в шаблонах для проверки, находитесь ли вы в режимеDEBUG. -
sql_queries– Список словарей{'sql': ..., 'time': ...}, представляющий все запросы к базе данных, которые произошли до настоящего момента во время обработки запроса, и время выполнения. Список отсортирован по имени базы данных, а затем по запросу. Он создается по мере необходимости.
django.template.context_processors.i18n
-
i18n(request)[source]
Если этот обработчик включен, каждый 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)[source]
Если этот процессор включён, в каждой RequestContext будет переменная STATIC_URL, содержащая значение настройки STATIC_URL.
django.template.context_processors.csrf
Этот процессор добавляет токен, необходимый тегу шаблона csrf_token для защиты от межсайтовых атак (CSRF).
django.template.context_processors.request
Если этот процессор включён, в каждой RequestContext будет переменная request, содержащая текущий HttpRequest.
django.template.context_processors.tz
-
tz(request)[source]
Если этот процессор включён, в каждой 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, или вообще не иметь расширения.
Обратите внимание, что эти пути должны использовать косые черты, даже на 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в памяти. Экземпляр кэширующего загрузчика возвращается для последующих запросов по загрузке того же шаблона.Этот загрузчик автоматически включён, если не указан
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[source] -
Загружает шаблоны из заданного источника, например, из файловой системы или базы данных.
-
get_template_sources(template_name)[source] -
Метод, который принимает
template_nameи возвращаетOriginэкземпляры для каждого возможного источника.Например, загрузчик из файловой системы может получить
'index.html'в качествеtemplate_nameаргумента. Этот метод вернёт объекты `Origin` для полного путиindex.htmlв каждом каталоге шаблонов, которые рассматриваются загрузчиком.Метод не обязан проверять существование шаблона по заданному пути, но должен убедиться, что путь корректен. Например, загрузчик из файловой системы проверяет, что путь лежит внутри допустимого каталога шаблонов.
-
get_contents(origin) -
Возвращает содержимое шаблона для заданного экземпляра
Origin.Здесь загрузчик из файловой системы будет читать содержимое из файловой системы, а загрузчик из базы данных — из базы данных. Если соответствующий шаблон не существует, должно быть выброшено исключение
TemplateDoesNotExist.
-
get_template(template_name, skip=None)[source] -
Возвращает объект
Templateдля заданногоtemplate_name, перебирая результаты изget_template_sources()и вызываяget_contents(). Возвращает первый найденный шаблон. Если шаблон не найден, вызывается исключениеTemplateDoesNotExist.Необязательный аргумент
skip— список кортежей `Origin`, которые следует игнорировать при расширении шаблонов. Это позволяет шаблонам расширять другие шаблоны с тем же именем. Это также используется для предотвращения рекурсивных ошибок.В целом, достаточно определить
get_template_sources()иget_contents()для пользовательских загрузчиков шаблонов.get_template()обычно переопределять не нужно.
-
Создание своего
Примеры можно найти в коде встроенных загрузчиков Django.
Происхождение шаблона
Шаблоны имеют origin содержащий атрибуты, зависящие от источника их загрузки.
-
class Origin(name, template_name=None, loader=None)[source] -
-
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/5.1/ref/templates/api/