Spec-Zone.ru › Django 5.2

Язык шаблонов 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.backends.django.Template, который оборачивает фактический django.template.Template.
  3. Template, полученный на предыдущем шаге, имеет метод render(), который передает контекст и, возможно, запрос в Context и делегирует рендеринг базовому Template.

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

Если вы используете бэкенд DjangoTemplates, это, вероятно, не та документация, которую вы ищете. Экземпляр класса Engine, описанного ниже, доступен через атрибут engine этого бэкенда, и любые значения по умолчанию, упомянутые ниже, переопределяются значениями, переданными DjangoTemplates.

class Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None, autoescape=True) [source]

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

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

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

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

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

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

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

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

    Устанавливайте это значение в False только если рендерите не HTML-шаблоны!

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

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

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

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

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

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

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

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

    Эти загрузчики затем оборачиваются в django.template.loaders.cached.Loader.

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

  • string_if_invalid — строка, которую система шаблонов должна использовать для недействительных (например, неправильно написанных) переменных.

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

    См. Как обрабатываются недействительные переменные шаблонов для получения подробностей.

  • file_charset — кодировка символов, используемая для чтения файлов шаблонов на диске.

    По умолчанию 'utf-8'.

  • 'libraries': Словарь меток и именованных путей к модулям тегов шаблонов для регистрации в движке шаблонов. Это используется для добавления новых библиотек или предоставления альтернативных меток для существующих. Например:

    Engine(
        libraries={
            "myapp_tags": "path.to.myapp.tags",
            "admin.urls": "django.contrib.admin.templatetags.admin_urls",
        },
    )
    

    Библиотеки могут быть загружены, передав соответствующий ключ словаря тегу {% load %}.

  • 'builtins': Список именованных путей к модулям тегов шаблонов для добавления в встроенные. Например:

    Engine(
        builtins=["myapp.builtins"],
    )
    

    Теги и фильтры из встроенных библиотек могут быть использованы без предварительного вызова тега {% load %}.

static Engine.get_default() [source]

Возвращает базовый Engine из первого настроенного бэкенда DjangoTemplates движка. Вызывает ImproperlyConfigured, если движки не настроены.

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

Engine.from_string(template_code) [source]

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

Engine.get_template(template_name) [source]

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

Engine.select_template(template_name_list) [source]

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

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

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

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

class Template [source]

Этот класс расположен по адресу django.template.Template. Конструктор принимает один аргумент — исходный код шаблона:

from django.template import Template

template = Template("My name is {{ my_name }}.")

За кулисами

Система анализирует ваш исходный код шаблона только один раз — при создании объекта Template. После этого он хранится во внутренней структуре дерева для повышения производительности.

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

Отрисовка контекста

После того, как у вас есть скомпилированный объект Template, вы можете отрисовать контекст с его помощью. Вы можете повторно использовать один и тот же шаблон для отрисовки несколько раз с разными контекстами.

class Context(dict_=None, autoescape=True, use_l10n=None, use_tz=None) [source]

Конструктор django.template.Context принимает необязательный аргумент — словарь, сопоставляющий имена переменных со значениями переменных.

Также можно указать три необязательных ключевых аргумента:

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

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

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

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

  • use_l10n переопределяет, будут ли значения по умолчанию локализованы. Если установить значение True, числа и даты будут отформатированы в соответствии с локалью.

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

    См. Управление локализацией в шаблонах для получения подробностей.

  • use_tz переопределяет, будут ли даты преобразовываться в местное время при рендеринге в шаблоне. Если установить значение True, все даты будут отображаться с использованием местного часового пояса. Это имеет приоритет над USE_TZ.

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

    См. Работа с часовыми поясами в шаблонах для получения подробностей.

Пример использования см. в разделе Работа с объектами Context ниже.

Template.render(context) [source]

Вызовите метод render() объекта Template с Context для «заполнения» шаблона:

>>> from django.template import Context, Template
>>> template = Template("My name is {{ my_name }}.")

>>> context = Context({"my_name": "Adrian"})
>>> template.render(context)
"My name is Adrian."

>>> context = Context({"my_name": "Dolores"})
>>> template.render(context)
"My name is Dolores."

Переменные и обращения к данным

Имена переменных должны состоять из любых букв (A-Z), любых цифр (0-9), подчеркивания (но они не должны начинаться с подчеркивания) или точки.

Точки имеют особое значение в рендеринге шаблонов. Точка в имени переменной обозначает обращение к данным. В частности, когда система шаблонов встречает точку в имени переменной, она пытается выполнить следующие обращения в указанном порядке:

  • Обращение к словарю. Пример: foo["bar"]
  • Обращение к атрибуту. Пример: foo.bar
  • Обращение по индексу списка. Пример: foo[bar]

Обратите внимание, что «bar» в выражении шаблона, например, {{ foo.bar }}, будет интерпретировано как буквальная строка, а не как значение переменной «bar», если она существует в контексте шаблона.

Система шаблонов использует первый тип обращения, который работает. Это логика короткого замыкания. Вот несколько примеров:

>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."

>>> class PersonClass:
...     pass
...
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."

>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."

Если какая-либо часть переменной является вызываемым объектом, система шаблонов попытается вызвать его. Пример:

>>> class PersonClass2:
...     def name(self):
...         return "Samantha"
...
>>> t = Template("My name is {{ person.name }}.")
>>> t.render(Context({"person": PersonClass2}))
"My name is Samantha."

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

  • Если при вызове переменной возникает исключение, это исключение будет передано, если у исключения нет атрибута silent_variable_failure со значением True. Если исключение имеет атрибут silent_variable_failure со значением True, переменная будет отображаться как значение конфигурации движка 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 DoesNotExist, имеет silent_variable_failure = True. Поэтому, если вы используете Django-шаблоны с объектами Django-моделей, любое исключение DoesNotExist будет проигнорировано.

  • Переменная может быть вызвана только в случае отсутствия обязательных аргументов. В противном случае система вернёт значение параметра движка string_if_invalid.
  • При вызове некоторых переменных могут возникнуть побочные эффекты, и позволить системе шаблонов к ним получить доступ было бы либо глупо, либо небезопасно.

    Хороший пример — метод delete() для каждого объекта модели Django. Системе шаблонов не следует разрешать делать что-то подобное:

    I will now delete this valuable data. {{ data.delete }}
    

    Чтобы предотвратить это, установите атрибут alters_data на вызываемую переменную. Система шаблонов не будет вызывать переменную, если у нее установлен атрибут alters_data=True, а вместо этого будет подменять переменную значением string_if_invalid безусловно. Динамически сгенерированные методы delete() и save() для объектов Django-моделей автоматически получают alters_data=True. Пример:

    def sensitive_function(self):
        self.database_record.delete()
    
    
    sensitive_function.alters_data = True
    
  • Иногда по каким-то причинам может потребоваться отключить эту функцию и указать системе шаблонов не вызывать переменную независимо от чего. Для этого установите атрибут do_not_call_in_templates на вызываемой переменной со значением True. Система шаблонов затем будет действовать так, как если бы ваша переменная не была вызываемой (позволяя вам получать доступ к атрибутам вызываемого объекта, например).

Обработка недопустимых переменных

В общем случае, если переменная не существует, система шаблонов вставляет значение конфигурации движка string_if_invalid, которое по умолчанию установлено в '' (пустая строка).

Фильтры, применяемые к невалидной переменной, будут применяться только если string_if_invalid установлено в '' (пустая строка). Если string_if_invalid установлено в любое другое значение, фильтры переменных будут проигнорированы.

Это поведение немного отличается для тегов шаблонов if, for и regroup. Если невалидная переменная предоставляется одному из этих тегов шаблонов, переменная будет интерпретирована как None. Фильтры всегда применяются к недопустимым переменным внутри этих тегов шаблонов.

Если string_if_invalid содержит '%s', маркер формата будет заменён именем невалидной переменной.

Только для отладки!

Хотя string_if_invalid может быть полезным инструментом для отладки, плохо использовать его в качестве «по умолчанию для разработки».

Многие шаблоны, включая некоторые из шаблонов Django, полагаются на бездействие системы шаблонов при обнаружении несуществующей переменной. Если вы присвоите значение, отличное от '', для string_if_invalid, вы столкнетесь с проблемами рендеринга в этих шаблонах и на сайтах.

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

Встроенные переменные

Каждый контекст содержит True, False и None. Как можно было ожидать, эти переменные разрешаются до соответствующих объектов Python.

Ограничения с буквальными строками

Язык шаблонов Django не имеет способа экранировать символы, используемые для его собственной синтаксической конструкции. Например, тег templatetag необходим, если вам нужно вывести последовательности символов, такие как {% и %}.

Аналогичная проблема возникает, если вы хотите включить эти последовательности в аргументы фильтров или тегов шаблонов. Например, при разборе тега блока Django-парсер шаблонов ищет первое вхождение %} после {%. Это предотвращает использование "%}" в качестве буквальной строки. Например, произойдёт исключение TemplateSyntaxError для следующих выражений:

{% include "template.html" tvar="Some string literal with %} in it." %}

{% with tvar="Some string literal with %} in it." %}{% endwith %}

Та же проблема может возникнуть при использовании зарезервированной последовательности в аргументах фильтра:

{{ some.variable|default:"}}" }}

Если вам необходимо использовать строки с этими последовательностями, храните их в переменных шаблонов или используйте пользовательский тег или фильтр шаблона для обхода ограничения.

Работа с объектами контекста

Большую часть времени вы создаёте объекты объектов контекста передавая в них полностью заполненный словарь в Context(). Но вы можете добавлять и удалять элементы из объекта Context после его создания, используя стандартную синтаксис словарей:

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c["foo"]
'bar'
>>> del c["foo"]
>>> c["foo"]
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c["newvariable"] = "hello"
>>> c["newvariable"]
'hello'
Context.get(key, otherwise=None)

Возвращает значение для key, если key присутствует в контексте, иначе возвращает otherwise.

Context.setdefault(key, default=None)

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

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

Объект Context является стеком. То есть, вы можете push() и pop() его. Если вы pop() слишком много, он выбросит исключение django.template.ContextPopException:

>>> c = Context()
>>> c["foo"] = "first level"
>>> c.push()
{}
>>> c["foo"] = "second level"
>>> c["foo"]
'second level'
>>> c.pop()
{'foo': 'second level'}
>>> c["foo"]
'first level'
>>> c["foo"] = "overwritten"
>>> c["foo"]
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
ContextPopException

Вы также можете использовать push() как менеджер контекста, чтобы убедиться, что вызывается соответствующая функция pop().

>>> c = Context()
>>> c["foo"] = "first level"
>>> with c.push():
...     c["foo"] = "second level"
...     c["foo"]
...
'second level'
>>> c["foo"]
'first level'

Все аргументы, переданные в push(), будут переданы конструктору dict, используемому для построения нового уровня контекста.

>>> c = Context()
>>> c["foo"] = "first level"
>>> with c.push(foo="second level"):
...     c["foo"]
...
'second level'
>>> c["foo"]
'first level'
Context.update(other_dict) [source]

Помимо push() и pop(), объект Context также определяет метод update(). Он работает как push(), но принимает словарь в качестве аргумента и помещает этот словарь на стек вместо пустого.

>>> c = Context()
>>> c["foo"] = "first level"
>>> c.update({"foo": "updated"})
{'foo': 'updated'}
>>> c["foo"]
'updated'
>>> c.pop()
{'foo': 'updated'}
>>> c["foo"]
'first level'

Как и push(), вы можете использовать update() как менеджер контекста, чтобы убедиться, что вызывается соответствующая функция pop().

>>> c = Context()
>>> c["foo"] = "first level"
>>> with c.update({"foo": "second level"}):
...     c["foo"]
...
'second level'
>>> c["foo"]
'first level'

Использование Context как стека бывает полезно в некоторых пользовательских тегах шаблонов.

Context.flatten()

Используя метод flatten(), вы можете получить весь Context стек как один словарь, включая встроенные переменные.

>>> c = Context()
>>> c["foo"] = "first level"
>>> c.update({"bar": "second level"})
{'bar': 'second level'}
>>> c.flatten()
{'True': True, 'None': None, 'foo': 'first level', 'False': False, 'bar': 'second level'}

Метод flatten() также используется внутри для сравнения объектов Context.

>>> c1 = Context()
>>> c1["foo"] = "first level"
>>> c1["bar"] = "second level"
>>> c2 = Context()
>>> c2.update({"bar": "second level", "foo": "first level"})
{'foo': 'first level', 'bar': 'second level'}
>>> c1 == c2
True

Результат от flatten() может быть полезен в модульных тестах для сравнения Context с dict:

class ContextTest(unittest.TestCase):
    def test_against_dictionary(self):
        c1 = Context()
        c1["update"] = "value"
        self.assertEqual(
            c1.flatten(),
            {
                "True": True,
                "None": None,
                "False": False,
                "update": "value",
            },
        )

Использование RequestContext

class RequestContext(request, dict_=None, processors=None, use_l10n=None, use_tz=None, autoescape=True) [source]

Django поставляется со специальным классом объекта контекста, django.template.RequestContext, который ведет себя немного иначе, чем обычный django.template.Context. Первое отличие заключается в том, что он принимает объект запроса в качестве первого аргумента. Например:

c = RequestContext(
    request,
    {
        "foo": "bar",
    },
)

Второе отличие заключается в том, что он автоматически заполняет контекст несколькими переменными в соответствии с настройкой context_processors движка.

Настройка context_processors представляет собой список вызовов — обработчиков контекста — которые принимают объект запроса в качестве аргумента и возвращают словарь элементов, которые нужно объединить в контекст. В файле настроек по умолчанию сгенерированный по умолчанию движок шаблонов содержит следующие обработчики контекста:

[
    "django.template.context_processors.request",
    "django.contrib.auth.context_processors.auth",
    "django.contrib.messages.context_processors.messages",
]

Помимо этого, RequestContext всегда включает 'django.template.context_processors.csrf'. Это связанный с безопасностью обработчик контекста, необходимый для админки и других приложений contrib, и, в случае случайной неправильной настройки, он преднамеренно жёстко закодирован и не может быть отключен в настройке context_processors.

Каждый обработчик применяется в порядке следования. Это означает, что если один обработчик добавляет переменную в контекст, а второй обработчик добавляет переменную с тем же именем, второй перепишет первый. Обработчики по умолчанию описаны ниже.

Когда применяются обработчики контекста

Обработчики контекста применяются поверх данных контекста. Это означает, что обработчик контекста может перезаписать переменные, которые вы предоставили своему Context или RequestContext, поэтому будьте внимательны, чтобы избежать совпадений имён переменных.

Если вы хотите, чтобы данные контекста имели приоритет над обработчиками контекста, используйте следующий шаблон:

from django.template import RequestContext

request_context = RequestContext(request)
request_context.push({"my_name": "Adrian"})

Django делает это, чтобы разрешить данным контекста переопределять обработчики контекста в API, таких как render() и TemplateResponse.

Также вы можете предоставить RequestContext список дополнительных обработчиков, используя необязательный третий позиционный аргумент, processors. В этом примере экземпляр RequestContext получает переменную ip_address:

from django.http import HttpResponse
from django.template import RequestContext, Template


def ip_address_processor(request):
    return {"ip_address": request.META["REMOTE_ADDR"]}


def client_ip_view(request):
    template = Template("{{ title }}: {{ ip_address }}")
    context = RequestContext(
        request,
        {
            "title": "Your IP Address",
        },
        [ip_address_processor],
    )
    return HttpResponse(template.render(context))

Встроенные обработчики контекста

Вот что делает каждый из встроенных обработчиков:

django.contrib.auth.context_processors.auth

auth(request) [source]

Если этот обработчик включен, каждый RequestContext будет содержать эти переменные:

  • user – Экземпляр auth.User, представляющий текущего авторизованного пользователя (или экземпляр AnonymousUser, если клиент не авторизован).
  • perms – Экземпляр django.contrib.auth.context_processors.PermWrapper, представляющий разрешения текущего авторизованного пользователя.

django.template.context_processors.debug

debug(request) [source]

Если этот обработчик включён, каждый RequestContext будет содержать эти две переменные — но только если ваша настройка DEBUG установлена в значение True, и адрес IP запроса (request.META['REMOTE_ADDR']) находится в настройке INTERNAL_IPS:

  • debug – True. Вы можете использовать это в шаблонах, чтобы проверить, находитесь ли вы в режиме DEBUG.
  • sql_queries – Список словарей {'sql': ..., 'time': ...}, представляющих каждую SQL-запрос, выполненную во время обработки запроса, и время его выполнения. Список отсортирован по имени базы данных и затем по запросу. Он генерируется лениво при доступе.

django.template.context_processors.i18n

i18n(request) [source]

Если этот обработчик включён, каждый RequestContext будет содержать эти переменные:

  • LANGUAGES – Значение настройки LANGUAGES.
  • LANGUAGE_BIDI – True, если текущий язык является языком справа налево, например, иврит, арабский. False, если это язык слева направо, например, английский, французский, немецкий.
  • LANGUAGE_CODE – request.LANGUAGE_CODE, если он существует. В противном случае, значение настройки LANGUAGE_CODE.

См. метки шаблона i18n для меток шаблона, которые генерируют те же значения.

django.template.context_processors.media

Если этот обработчик включен, каждый RequestContext будет содержать переменную MEDIA_URL, предоставляющую значение настройки MEDIA_URL.

django.template.context_processors.static

static(request) [source]

Если этот обработчик включён, каждый RequestContext будет содержать переменную STATIC_URL, предоставляющую значение настройки STATIC_URL.

django.template.context_processors.csrf

Этот обработчик добавляет токен, необходимый метке шаблона csrf_token для защиты от межсайтовых поддельных запросов.

django.template.context_processors.request

Если этот обработчик включен, каждый RequestContext будет содержать переменную request, которая является текущим объектом HttpRequest.

django.template.context_processors.tz

tz(request) [source]

Если этот обработчик включён, каждый RequestContext будет содержать переменную TIME_ZONE, предоставляющую имя текущей активной часовой зоны.

django.contrib.messages.context_processors.messages

Если этот обработчик включён, каждый RequestContext будет содержать эти две переменные:

  • messages – Список сообщений (в виде строк), установленных через фреймворк сообщений.
  • DEFAULT_MESSAGE_LEVELS – Сопоставление имён уровней сообщений с их числовыми значениями.

Создание собственных обработчиков контекста

Обработчик контекста имеет простой интерфейс: это функция Python, которая принимает один аргумент, объект HttpRequest, и возвращает словарь, который добавляется в контекст шаблона.

Например, чтобы добавить настройку DEFAULT_FROM_EMAIL в каждый контекст:

from django.conf import settings


def from_email(request):
    return {
        "DEFAULT_FROM_EMAIL": settings.DEFAULT_FROM_EMAIL,
    }

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

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

Как правило, вы будете хранить шаблоны в файлах на вашей файловой системе, а не использовать низкоуровневый API Template самостоятельно. Сохраняйте шаблоны в каталоге, указанном как каталог шаблонов.

Django ищет каталоги шаблонов в нескольких местах, в зависимости от настроек загрузки шаблонов (см. «Типы загрузчиков» ниже), но самый простой способ указать каталоги шаблонов — использовать параметр DIRS.

Параметр DIRS

Укажите Django свои каталоги шаблонов, используя параметр DIRS в настройке TEMPLATES в вашем файле настроек — или аргумент dirs для Engine. Он должен быть установлен в список строк, содержащих полные пути к вашим каталогам шаблонов:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            "/home/html/templates/lawrence.com",
            "/home/html/templates/default",
        ],
    },
]

Шаблоны могут располагаться где угодно, при условии, что каталоги и шаблоны доступны для веб-сервера. Они могут иметь любое расширение, например .html или .txt, или вообще не иметь расширения.

Обратите внимание, что эти пути должны использовать косые черты в стиле 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, вы можете переопределить стандартный admin/base_site.html шаблон из django.contrib.admin своим собственным admin/base_site.html в myproject.polls. Тогда вы должны убедиться, что ваше myproject.polls стоит перед django.contrib.admin в INSTALLED_APPS, иначе django.contrib.admin будут загружены первыми, и ваши будут проигнорированы.

Обратите внимание, что загрузчик выполняет оптимизацию при первом запуске: он кэширует список пакетов INSTALLED_APPS, у которых есть подкаталог templates.

Вы можете включить этот загрузчик, установив APP_DIRS в True:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "APP_DIRS": True,
    }
]

django.template.loaders.cached.Loader

class cached.Loader

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

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

Этот загрузчик автоматически включён, если OPTIONS['loaders'] не указан.

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

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "OPTIONS": {
            "loaders": [
                (
                    "django.template.loaders.cached.Loader",
                    [
                        "django.template.loaders.filesystem.Loader",
                        "django.template.loaders.app_directories.Loader",
                        "path.to.custom.Loader",
                    ],
                ),
            ],
        },
    }
]

Примечание

Все встроенные теги шаблонов Django безопасны для использования с кэширующим загрузчиком, но если вы используете пользовательские теги шаблонов из пакетов сторонних разработчиков или написанные вами сами, вы должны убедиться, что реализация Node для каждого тега является потокобезопасной. Для получения дополнительной информации см. учетные соображения по потоковой безопасности тегов шаблонов.

django.template.loaders.locmem.Loader

class locmem.Loader

Загружает шаблоны из словаря Python. Это полезно для тестирования.

Этот загрузчик принимает словарь шаблонов в качестве первого аргумента:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "OPTIONS": {
            "loaders": [
                (
                    "django.template.loaders.locmem.Loader",
                    {
                        "index.html": "content here",
                    },
                ),
            ],
        },
    }
]

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

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

Настраиваемые загрузчики

Возможно загружать шаблоны из дополнительных источников с помощью настраиваемых загрузчиков шаблонов. Настраиваемые Loader классы должны наследоваться от django.template.loaders.base.Loader и определять методы get_contents() и get_template_sources().

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

class Loader [source]

Загружает шаблоны из заданного источника, такого как файловая система или база данных.

get_template_sources(template_name) [source]

Метод, который принимает template_name и возвращает Origin объекты для каждого возможного источника.

Например, загрузчик файловой системы может получить 'index.html' в качестве template_name аргумента. Этот метод вернёт объекты `Origin` для полного пути к index.html, как он отображается в каждом каталоге шаблонов, который просматривает загрузчик.

Методу не нужно проверять, существует ли шаблон по заданному пути, но он должен убедиться, что путь корректен. Например, загрузчик файловой системы проверяет, лежит ли путь в пределах допустимого каталога шаблонов.

get_contents(origin)

Возвращает содержимое шаблона, заданного объектом Origin.

Здесь загрузчик файловой системы читает содержимое из файловой системы, а загрузчик базы данных — из базы данных. Если соответствующего шаблона не существует, должно быть выброшено исключение TemplateDoesNotExist.

get_template(template_name, skip=None) [source]

Возвращает объект Template для заданного template_name, перебирая результаты из get_template_sources() и вызывая get_contents(). Это возвращает первый соответствующий шаблон. Если шаблон не найден, поднимается исключение TemplateDoesNotExist.

Необязательный аргумент skip — список объектов `Origin`, которые нужно пропустить при расширении шаблонов. Это позволяет шаблонам расширять другие шаблоны с тем же именем. Это также используется для предотвращения рекурсивных ошибок.

В общем случае достаточно определить get_template_sources() и get_contents() для настраиваемых загрузчиков шаблонов. get_template() обычно переопределять не нужно.

Разработка своего загрузчика

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

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

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

class Origin(name, template_name=None, loader=None) [source]
name

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

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

template_name

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

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

loader

Экземпляр загрузчика шаблонов, который создал этот Origin.

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

django.template.loaders.cached.Loader требует, чтобы все его обернутые загрузчики установили этот атрибут, обычно, создавая Origin с loader=self.

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

Spec-Zone.ru

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