Spec-Zone.ru › Django 1.10

Язык шаблонов Django: для программистов Python

Этот документ объясняет систему шаблонов Django с технической точки зрения — как она работает и как ее расширить. Если вы ищете только справочную информацию по синтаксису языка, см. Язык шаблонов Django.

Предполагается понимание шаблонов, контекстов, переменных, тегов и рендеринга. Начните с введения в язык шаблонов Django, если вы не знакомы с этими понятиями.

Обзор

Использование системы шаблонов на Python — трехступенчатый процесс:

  1. Вы настраиваете Engine.
  2. Вы компилируете код шаблона в Template.
  3. Вы рендерите шаблон с помощью Context.

Проекты Django обычно полагаются на API высокого уровня, независимые от бэкенда на каждом из этих шагов вместо API системы шаблонов низкого уровня:

  1. Для каждого DjangoTemplates бэкенда в настройке TEMPLATES, Django инициализирует Engine. DjangoTemplates оборачивает Engine и адаптирует его к обычному API бэкенда шаблонов.
  2. Модуль django.template.loader предоставляет функции, такие как get_template() для загрузки шаблонов. Они возвращают обёртку над фактическим django.template.Template.
  3. Полученный на предыдущем шаге объект имеет метод render(), который обрабатывает контекст и, возможно, запрос в Context и делегирует рендеринг нашему Template.

Настройка движка

Если вы просто используете бэкенд DjangoTemplates, этот документ, вероятно, не то, что вам нужно. Экземпляр класса нижеописанного класса доступен через атрибут бэкенда, а любые указанные ниже значения по умолчанию переопределяются тем, что передаётся 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]

При создании экземпляра все аргументы должны передаваться в качестве именованных аргументов:

  • dirs — список каталогов, в которых движок должен искать файлы шаблонов. Он используется для настройки filesystem.Loader.

    По умолчанию пустой список.

  • app_dirs влияет только на значение по умолчанию loaders. См. ниже.

    По умолчанию False.

  • autoescape определяет, включена ли автоматическая экранировка HTML.

    По умолчанию True.

    Предупреждение

    Установите его только в False, если вы рендерите не HTML-шаблоны!

    Добавлено в Django 1.10:

    Параметр autoescape был добавлен.

  • context_processors — список имён функций Python, используемых для заполнения контекста, когда шаблон рендерится с запросом. Эти функции принимают объект запроса в качестве аргумента и возвращают словарь элементов, которые должны быть объединены в контекст.

    По умолчанию пустой список.

    См. RequestContext для дополнительной информации.

  • debug — логический флаг, включающий/выключающий режим отладки шаблонов. Если он равен True, движок шаблонов будет хранить дополнительную отладочную информацию, которая может быть использована для отображения подробного отчета об ошибках, возникающих во время рендеринга шаблонов.

    По умолчанию False.

  • loaders — список классов загрузчиков шаблонов, указанных в виде строк. Каждый класс Loader знает, как импортировать шаблоны из определенного источника. Допускается использование кортежей вместо строк. Первый элемент кортежа должен быть именем класса Loader, последующие элементы передаются загрузчику Loader во время инициализации.

    По умолчанию список, содержащий:

    • 'django.template.loaders.filesystem.Loader'
    • 'django.template.loaders.app_directories.Loader' только если app_dirs равен True.

    См. Типы загрузчиков для получения подробностей.

  • 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 %}.

Добавлено в Django 1.9:

Аргументы libraries и builtins были добавлены.

static Engine.get_default() [source]

Когда проект Django настраивает один и только один движок DjangoTemplates, этот метод возвращает основной Engine. В других случаях он генерирует ImproperlyConfigured.

Это необходимо для сохранения API, которые полагаются на глобально доступный, неявным образом настроенный движок. Любое другое использование настоятельно не рекомендуется.

Engine.from_string(template_code) [source]

Компилирует заданный код шаблона и возвращает объект Template.

Engine.get_template(template_name) [source]

Загружает шаблон с заданным именем, компилирует его и возвращает объект Template.

Engine.select_template(self, template_name_list) [source]

Подобно get_template(), за исключением того, что он принимает список имён и возвращает первый найденный шаблон.

Загрузка шаблона

Рекомендуемый способ создания Template — вызов методов-фабрик Engine: get_template(), select_template() и from_string().

В проекте Django, где настройка TEMPLATES определяет ровно один DjangoTemplates движок, можно создать Template напрямую.

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)
Добавлен в Django 1.9.

Если key находится в контексте, возвращает его значение. В противном случае вставляет key со значением default и возвращает default.

Context.pop()
Context.push()
END_OF_DOCUMENT_MARKER
exception ContextPopException [source]

Объект Context является стеком. То есть, вы можете pop() и 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'
Добавлено в Django 1.9:

Была добавлена возможность использования update() в качестве менеджера контекста.

Использование 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 1.10:

В более ранних версиях включались только запросы для базы данных по умолчанию.

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, или вообще не иметь расширения.

Обратите внимание, что эти пути должны использовать обратные слэши в стиле 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': [os.path.join(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.eggs.Loader

class eggs.Loader

Устарело начиная с версии 1.9: Распространение приложений в виде пакетов eggs не рекомендуется.

Точно так же, как и app_directories выше, но он загружает шаблоны из Python-пакетов eggs, а не с файловой системы.

Этот загрузчик по умолчанию отключён.

django.template.loaders.cached.Loader

class cached.Loader

По умолчанию система шаблонизации будет читать и компилировать ваши шаблоны каждый раз, когда они требуются для рендеринга. Хотя система шаблонизации Django довольно быстрая, накладные расходы от чтения и компиляции шаблонов могут накапливаться.

Загрузчик кэшированных шаблонов — это загрузчик на основе класса, который вы настраиваете с помощью списка других загрузчиков, которые он должен обернуть. Обернутые загрузчики используются для поиска неизвестных шаблонов, когда они встречаются впервые. Загрузчик кэша затем сохраняет скомпилированные Template в памяти. Кэшированный экземпляр Template возвращается для последующих запросов на загрузку того же шаблона.

Например, для включения кэширования шаблонов с загрузчиками filesystem и app_directories вы можете использовать следующие настройки:

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',
            ]),
        ],
    },
}]

Примечание

Все встроенные теги 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().

Изменено в Django 1.9:

В предыдущих версиях Django пользовательские загрузчики определяли один метод: load_template_source().

Методы загрузчика

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() обычно переопределять не нужно.

load_template_source(template_name, template_dirs=None) [source]

Возвращает кортеж (template_string, template_origin), где template_string — строка, содержащая содержимое шаблона, а template_origin — строка, определяющая источник шаблона. Загрузчик на основе файловой системы может вернуть полный путь к файлу в качестве template_origin, например.

template_dirs — необязательный аргумент, используемый для управления каталогами, которые будет искать загрузчик.

Этот метод вызывается автоматически методом load_template() и должен быть переопределён при написании пользовательских загрузчиков шаблонов.

Устарело начиная с версии 1.9: Пользовательские загрузчики должны использовать get_template() и get_contents() вместо этого.

load_template(template_name, template_dirs=None) [source]

Возвращает кортеж (template, template_origin), где template — объект Template, а template_origin — строка, определяющая источник шаблона. Загрузчик на основе файловой системы может вернуть полный путь к файлу в качестве template_origin, например.

Устарело начиная с версии 1.9: Пользовательские загрузчики должны использовать get_template() и get_contents() вместо этого.

Создание своего

Для примеров прочитайте исходный код встроенных загрузчиков Django.

Происхождение шаблона

Шаблоны имеют origin с атрибутами, зависящими от источника, из которого они загружены.

Изменено в Django 1.9:

Django раньше создавал происхождение на основе django.template.loader.LoaderOrigin или django.template.base.StringOrigin. Теперь используется django.template.base.Origin.

class Origin [source]
name

Путь к шаблону, возвращаемый загрузчиком шаблонов. Для загрузчиков, которые читают из файловой системы, это полный путь к шаблону.

Если шаблон инициализирован непосредственно, а не через загрузчик шаблонов, это строковое значение <unknown_source>.

template_name

Относительный путь к шаблону, переданный в загрузчик шаблонов.

Если шаблон инициализирован непосредственно, а не через загрузчик шаблонов, это None.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.10/ref/templates/api/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API