Язык шаблонов Django для программистов Python
Этот документ объясняет систему шаблонов Django с технической точки зрения — как она работает и как её расширить. Если вам нужна только справочная информация по синтаксису языка, см. Язык шаблонов Django.
Предполагается, что вы знакомы с понятиями шаблонов, контекстов, переменных, тегов и рендеринга. Если вы не знакомы с этими понятиями, начните с введения в язык шаблонов Django.
Обзор
Использование системы шаблонов на Python — это трёхэтапный процесс:
- Вы настраиваете
Engine. - Вы компилируете код шаблона в
Template. - Вы рендерите шаблон с помощью
Context.
Проекты Django обычно полагаются на API высокого уровня, не зависящий от бэкенда для каждого из этих этапов вместо API системы шаблонов низкого уровня:
- Для каждого бэкенда
DjangoTemplatesв настройкеTEMPLATES, Django инициализируетEngine.DjangoTemplatesоборачиваетEngineи адаптирует его к общему API бэкенда шаблонов. - Модуль
django.template.loaderпредоставляет функции, такие какget_template()для загрузки шаблонов. Они возвращаютdjango.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.
Если
debugравенFalse, эти загрузчики оборачиваются вdjango.template.loaders.cached.Loader.См. Типы загрузчиков для получения подробной информации.
Изменено в Django 1.11:Была добавлена возможность включения кэшированного загрузчика шаблонов, когда
debugравенFalse. -
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()[source] -
Возвращает базовый
Engineиз первого настроенного бэкендаDjangoTemplates. ВызываетImproperlyConfigured, если нет настроенных движков.Необходим для сохранения API, которые полагаются на глобально доступный, неявно настроенный движок. Любое другое использование строго не рекомендуется.
Изменено в Django 2.0:В более старых версиях вызывает
ImproperlyConfiguredесли настроено несколько движков, а не возвращает первый движок.
-
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)[source] -
Конструктор
django.template.Contextпринимает необязательный аргумент — словарь, сопоставляющий имена переменных с их значениями.Подробности см. в разделе Работа с объектами 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, переменная будет отображена как значение параметра настройки движка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 базы данных 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 может быть полезным инструментом отладки, не рекомендуется включать его по умолчанию для разработки.
Многие шаблоны, включая те, что на странице администратора, полагаются на то, что система шаблонов ничего не делает при обнаружении несуществующей переменной. Если вы присвоите значение, отличное от '' переменной 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[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)[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()[source]
Если этот обработчик включен, каждый RequestContext будет содержать эти переменные:
-
user– Экземплярauth.User, представляющий текущего пользователя, авторизованного в системе (или экземплярAnonymousUserв случае, если клиент не авторизован). -
perms– Экземплярdjango.contrib.auth.context_processors.PermWrapper, представляющий разрешения, имеющиеся у текущего авторизованного пользователя.
django.template.context_processors.debug
-
debug()[source]
Если этот обработчик включен, каждый RequestContext будет содержать эти две переменные – но только если ваша настройка DEBUG установлена в True и IP-адрес запроса (request.META['REMOTE_ADDR']) находится в настройке INTERNAL_IPS:
-
debug–True. Вы можете использовать это в шаблонах для проверки, находитесь ли вы в режимеDEBUG. -
sql_queries– Список словарей{'sql': ..., 'time': ...}, представляющих каждую SQL-запрос, который произошел до сих пор во время запроса, и сколько времени это заняло. Список упорядочен по алиасу базы данных, а затем по запросу. Он генерируется лениво при обращении.
django.template.context_processors.i18n
Если этот обработчик включен, каждый RequestContext будет содержать эти две переменные:
-
LANGUAGES– Значение настройкиLANGUAGES. -
LANGUAGE_CODE–request.LANGUAGE_CODE, если он существует. В противном случае значение настройкиLANGUAGE_CODE.
См. Международная и локальная поддержка для получения дополнительной информации.
django.template.context_processors.media
Если этот обработчик включен, каждый RequestContext будет содержать переменную MEDIA_URL, содержащую значение настройки MEDIA_URL.
django.template.context_processors.static
-
static()[source]
Если этот обработчик включен, каждый RequestContext будет содержать переменную STATIC_URL, содержащую значение настройки STATIC_URL.
django.template.context_processors.csrf
Этот обработчик добавляет токен, необходимый тегу шаблона csrf_token для защиты от межсайтовых поддельных запросов.
django.template.context_processors.request
Если этот обработчик включен, каждый RequestContext будет содержать переменную request, которая представляет собой текущий объект HttpRequest.
django.template.context_processors.tz
-
tz()[source]
Если этот обработчик включен, каждый RequestContext будет содержать переменную TIME_ZONE, содержащую имя текущей активной временной зоны.
django.contrib.messages.context_processors.messages
Если этот процессор включён, каждый RequestContext будет содержать эти две переменные:
-
messages– Список сообщений (в виде строк), которые были установлены с помощью фреймворка сообщений. -
DEFAULT_MESSAGE_LEVELS– Сопоставление имён уровней сообщений с их числовыми значениями.
Создание собственных процессоров контекста
Процессор контекста имеет очень простой интерфейс: это функция Python, которая принимает один аргумент, объект HttpRequest, и возвращает словарь, который добавляется в контекст шаблона. Каждый процессор контекста обязательно должен возвращать словарь.
Пользовательские процессоры контекста могут находиться в любой части вашей кодовой базы. 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': [os.path.join(BASE_DIR, 'templates')], }]Вы также можете переопределить
'DIRS'и указать определённые каталоги для конкретного загрузчика файловой системы:TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'OPTIONS': { 'loaders': [ ( 'django.template.loaders.filesystem.Loader', [os.path.join(BASE_DIR, 'templates')], ), ], }, }]Изменено в Django 1.11:Была добавлена возможность указывать каталоги для определённого загрузчика файловой системы.
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': [os.path.join(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 1.11:Добавлена автоматическая активация загрузчика кэшированных шаблонов, когда
debugравноFalse.
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/2.0/ref/templates/api/