Язык шаблонов Django: для Python программистов¶
Этот раздел описывает систему шаблонов Django с технической стороны – как она работает и как расширить её. Если вы ищите просто описание синтаксиса шаблонов, смотрите Язык шаблонов Django.
Этот документ подразумевает, что вы уже знакомы с шаблонами, контекстом, переменными, тегами и рендерингом. Если вам не знакомы эти концепции, начните с вступления в систему шаблонов Django.
Обзор¶
Система шаблонов в Python работает в два этапа:
Вы настраиваете
Engine.Сначала вы компилируете код шаблона в объект
Template.Вы рендерите шаблон с
Context.
Django использует высокоуровневый API, который не привязан к конкретному бэкенду:
Для каждого бэкенда
DjangoTemplatesиз настройки theTEMPLATES, Django создает экземпляр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.По умолчанию
False.Предупреждение
Устанавливайте значение «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.
If
debugisFalse, these loaders are wrapped indjango.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()¶
Если проект настроен на использование
DjangoTemplatesи только его, этот метод вернет соответствующийEngine. Иначе вызовет исключениеImproperlyConfigured.Необходим для совместимости API, который рассчитывает на глобальный, неявно настроенный механизм шаблонов. Не следует использовать для других ситуаций.
- Engine.get_template(template_name)¶
Загружает шаблон с указанным названием, компилирует его и возвращает объект
Template.
- Engine.select_template(template_name_list)¶
Похож на
get_template(), но принимает список шаблонов и возвращает первый доступный шаблон из списка.
Загрузка шаблонов¶
Рекомендуемый метод создать Template – использовать методы-фабрики Engine: get_template(), select_template() и from_string().
В проекте, где настройка TEMPLATES содержит только DjangoTemplates, можно создать экземпляр Template напрямую.
- 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 принимает необязательный аргумент — словарь, сопоставляющий имена переменных со значениями переменных.
For details, see Использование объекта Context below.
- Template.render(context)¶
Call the
Templateobject’srender()method with aContextto «fill» the template:>>> 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», а не переменная с названием «bar».
The template system uses the first lookup type that works. It’s short-circuit logic. Here are a few examples:
>>> 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."
If any part of the variable is callable, the template system will try calling it. Example:
>>> class PersonClass2:
... def name(self):
... return "Samantha"
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."
Вызываемые переменные работают немного сложнее. Вам следует помнить о следующем:
If the variable raises an exception when called, the exception will be propagated, unless the exception has an attribute
silent_variable_failurewhose value isTrue. If the exception does have asilent_variable_failureattribute whose value isTrue, the variable will render as the value of the engine’sstring_if_invalidconfiguration option (an empty string, by default). Example:>>> 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, который является родительским для всех ошибокDoesNotExistв ORM, содержитsilent_variable_failure = True. Поэтому, если вы используете объекты модели в шаблонах, исключениеDoesNotExistбудет проигнорировано.Функция из переменной может быть вызвана, только если не требует обязательных аргументов. В таком случае шаблон вставит вместо переменной значение
string_if_invalid.
Очевидно, что вызов функций может выполнять различные побочные действия, которые могут привести к уязвимостям, было бы глупо позволять шаблону выполнять их.
A good example is the
delete()method on each Django model object. The template system shouldn’t be allowed to do something like this:I will now delete this valuable data. {{ data.delete }}
Чтобы избежать этого, укажите атрибут
alters_dataв функции или методе. Шаблон не будет вызывать переменную, если значение содержитalters_data=True, и будет использовать значение настройкиstring_if_invalid. Встроенные методыdelete()иsave()модели содержат атрибут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 и полезная для отладки, лучше не менять её по умолчанию и использовать только при необходимости локально.
Многие шаблоны, включая шаблоны админки, полагаются на то, что неправильные переменные будут проигнорированы системой шаблонов. Если заменить '' в string_if_invalid на другое значение, могут возникнуть проблемы с рендерингом шаблонов.
Как правило string_if_invalid необходимо использовать для отладки конкретной проблемы в шаблоне, и после отладки возвращать значение по умолчанию.
Встроенные переменные¶
Каждый контекст содержит True, False и None. Как и следовало ожидать эти переменные соответствуют объектам Python.
Ограничения текстовых литералов¶
Система шаблонов Django не позволяет экранировать символы, которые используются в синтаксисе разметки шаблонов. Например, следует использовать тег templatetag, если необходимо вывести в шаблоне {% и %} как строки.
A similar issue exists if you want to include these sequences in template filter
or tag arguments. For example, when parsing a block tag, Django’s template
parser looks for the first occurrence of %} after a {%. This prevents
the use of "%}" as a string literal. For example, a TemplateSyntaxError
will be raised for the following expressions:
{% include "template.html" tvar="Some string literal with %} in it." %}
{% with tvar="Some string literal with %} in it." %}{% endwith %}
The same issue can be triggered by using a reserved sequence in filter arguments:
{{ some.variable|default:"}}" }}
Чтобы обойти эти ограничения, используйте переменную для хранения запрещенных строк, или свой теги или фильтр, чтобы обойти ограничения.
Использование объекта Context¶
Most of the time, you’ll instantiate Context objects by passing in a
fully-populated dictionary to Context(). But you can add and delete items
from a Context object once it’s been instantiated, too, using standard
dictionary syntax:
>>> 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¶
A Context object is a stack. That is, you can push() and pop() it.
If you pop() too much, it’ll raise
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',
})
Классы наследники Context: RequestContext¶
- class RequestContext(request, dict_=None, processors=None)¶
Django comes with a special Context class,
django.template.RequestContext, that acts slightly differently from the
normal django.template.Context. The first difference is that it takes an
HttpRequest as its first argument. For example:
c = RequestContext(request, {
'foo': 'bar',
})
Еще одно отличие – он автоматически добавляет различные переменные в соответствии с опцией context_processors шаблонизатора.
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.core.context_processors.csrf. Этот процессор контекста используется для безопасности админкой и другими встроенными приложениями. Чтобы исключить его случайное отключение, он захардкоден и не может быть выключен с помощью настройки 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 запросы и время их выполнения, которые были выполнены при обработке запроса. Список отсортирован в порядке выполнения 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 для защиты от CSRF атак.
django.template.context_processors.request¶
Если включить этот процессор, в RequestContext будет добавлена переменная request, содержащая текущий HttpRequest.
django.template.context_processors.static¶
- tz()¶
Если включить этот процессор, в RequestContext будет добавлена переменная MEDIA_URL, которая содержит значение MEDIA_URL.
django.contrib.messages.context_processors.messages¶
Если включить этот процессор, в RequestContext будут добавлены следующие переменные:
messages– список сообщений (строки), которые были добавлены с помощью фреймворка сообщений.DEFAULT_MESSAGE_LEVELS– словарь приоритетов сообщений и их числовых кодов.
Как создать свой процессор контекста¶
A context processor has a simple interface: It’s a Python function that takes
one argument, an HttpRequest object, and returns a
dictionary that gets added to the template context. Each context processor
must return a dictionary.
Код процессора может находится где угодно. Главное не забыть указать его в опции 'context_processors' настройки:setting: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.Вы можете включить этот загрузчик, указав
TrueвAPP_DIRS:TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'APP_DIRS': True, }]
django.template.loaders.cached.Loader
- class cached.Loader¶
By default (when
DEBUGisTrue), the template system reads and compiles your templates every time they’re rendered. While the Django template system is quite fast, the overhead from reading and compiling templates can add up.Кеширующий загрузчик шаблонов принимает список загрузчиков Он будет использовать их для поиска неизвестных шаблонов, которые загружаются первый раз. Затем скомпилированные
Templateсохраняются в памяти. Закешированный объектTemplateвозвращается при повторном поиске уже загруженного шаблона.This loader is automatically enabled if
OPTIONS['loaders']isn’t specified andOPTIONS['debug']isFalse(the latter option defaults to the value ofDEBUG).You can also enable template caching with some custom template loaders using settings like this:
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.