Язык шаблонов 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) -
При создании экземпляра
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.
Если
debugравноFalse, эти загрузчики оборачиваются в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) -
Конструктор
django.template.Contextпринимает необязательный аргумент — словарь, сопоставляющий имена переменных со значениями переменных.Подробности см. в разделе Работа с объектами 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, который является базовым классом для всех исключений API базы данных DjangoDoesNotExist, имеет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)
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()
Если этот обработчик включён, каждый RequestContext будет содержать эти переменные:
-
user– Экземплярauth.User, представляющий текущего авторизованного пользователя (или экземплярAnonymousUser, если клиент не авторизован). -
perms– Экземплярdjango.contrib.auth.context_processors.PermWrapper, представляющий разрешения текущего авторизованного пользователя.
django.template.context_processors.debug
-
debug()
Если этот обработчик включён, каждый RequestContext будет содержать эти две переменные — только если настройка DEBUG установлена в значение True и IP-адрес запроса (request.META['REMOTE_ADDR']) находится в настройке INTERNAL_IPS:
-
debug–True. Вы можете использовать это в шаблонах для проверки, находитесь ли вы в режимеDEBUG. -
sql_queries– Список словарей{'sql': ..., 'time': ...}, представляющих каждую SQL-запрос, который произошёл до этого момента во время обработки запроса, и сколько времени это заняло. Список упорядочен по имени базы данных и затем по запросу. Он генерируется лениво при доступе.
django.template.context_processors.i18n
-
i18n()
Если этот обработчик включён, каждый 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()
Если этот обработчик включён, каждый RequestContext будет содержать переменную STATIC_URL, предоставляющую значение настройки STATIC_URL.
django.template.context_processors.csrf
Этот обработчик добавляет маркер, необходимый тегу шаблона csrf_token для защиты от атак типа Cross-Site Request Forgery.
django.template.context_processors.request
Если этот обработчик включён, каждый RequestContext будет содержать переменную request, которая представляет текущий HttpRequest.
django.template.context_processors.tz
-
tz()
Если этот обработчик включён, каждый 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 -
По умолчанию (когда
DEBUGравноTrue), система шаблонов читает и компилирует ваши шаблоны каждый раз, когда они отображаются. Хотя система шаблонов Django довольно быстрая, накладные расходы от чтения и компиляции шаблонов могут накапливаться.Вы настраиваете кэширующий загрузчик шаблонов с помощью списка других загрузчиков, которые он должен обернуть. Обернутые загрузчики используются для поиска неизвестных шаблонов, когда они впервые встречаются. Затем кэширующий загрузчик хранит скомпилированные
Templateв памяти. Кэшированный экземплярTemplateвозвращается для последующих запросов на загрузку того же шаблона.Этот загрузчик автоматически включается, если
OPTIONS['loaders']не указан, аOPTIONS['debug']равенFalse(последняя опция по умолчанию имеет значениеDEBUG).Вы также можете включить кэширование шаблонов с помощью некоторых пользовательских загрузчиков шаблонов, используя такие настройки:
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/4.0/ref/templates/api/