Язык шаблонов 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 engine, и любые значения атрибута по умолчанию, упомянутые ниже, заменяются тем, что передается DjangoTemplates .

classEngine ( dirs = None , app_dirs = False , context_processors = None , debug = False , loaders = None , string_if_invalid = '' , file_charset = 'utf-8' , libraries = None , builtins = None , autoescape = True )

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

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

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

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

    Его значение по умолчанию - False .

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

    Его значение по умолчанию - True .

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

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

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

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

    См. RequestContext Дополнительную информацию.

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

    Его значение по умолчанию - False .

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

    Его значение по умолчанию - это список, содержащий:

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

    Если debug стоит False , зарядники завернуты django.template.loaders.cached.Loader .

    Подробнее см. Типы зарядных устройств .

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

    Его значение по умолчанию - пустая строка.

    См. Подробности в разделе « Обработка недопустимых переменных» .

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

    Его значение по умолчанию - 'utf-8' .

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

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

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

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

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

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

staticEngine.get_default ()

Возвращает Engine базовый механизм первого DjangoTemplates настроенного механизма . Генерируется, ImproperlyConfigured если двигатель не был настроен.

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

Engine.from_string( template_code )

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

Engine.get_template( имя_шаблона )

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

Engine.select_template( template_name_list )

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

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

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

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

класс Template

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

from django.template import Template

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

За кулисами

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

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

Рендеринг контекста

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

classContext ( dict_ = None )

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

Дополнительные сведения см. В разделе « Обработка объектов контекста» ниже.

Template.render( контекст )

Вызов этого 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."

Переменные и подэлементы

Имена переменных могут содержать буквы (AZ), цифры (0–9), символы подчеркивания и точки (но не могут начинаться с подчеркивания).

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

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

Обратите внимание, что «bar» в выражении шаблона интерпретируется как буквальная строка, и даже если в контексте шаблона существует переменная «bar», она не будет вызываться.{{ foo.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 . В последнем случае переменная создаст строку, эквивалентную содержимому параметра конфигурации 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 , что это базовый класс для всех исключений DoesNotExist API базы данных Django, содержащий . Итак, если вы используете шаблоны Django с объектами модели Django, любое исключение автоматически завершается ошибкой.silent_variable_failure = True DoesNotExist

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Управление объектами Context

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

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
Context.get( ключ , иначе = Нет )

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

Context.setdefault( ключ , по умолчанию = Нет )

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

Context.pop()
Context.push()
исключение ContextPopException

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

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

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

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

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

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

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

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

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

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

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

Context.flatten()

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

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

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

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

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

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

Используя RequestContext

classRequestContext ( запрос , dict_ = None , processors = None )

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

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

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

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

[
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
]

В дополнение к этому контенту RequestContext всегда активен 'django.template.context_processors.csrf' . Это связанный с безопасностью обработчик контекста, который требуется приложению администрирования, а также другим дополнительным приложениям. Он специально добавлен принудительно, чтобы его нельзя было удалить из-за ошибки конфигурации в опции context_processors .

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

Когда применяются контекстные процессоры?

Контекстные процессоры применяются поверх контекстных данных. Это означает, что процессор контекста может перезаписать переменную, которую вы указали в объекте, Context или RequestContext , поэтому будьте осторожны, чтобы не использовать переменные, имена которых могут конфликтовать с именами установленных процессоров контекста.

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

from django.template import RequestContext

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

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

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

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

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

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

Встроенные процессоры контекста шаблонов

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

django.contrib.auth.context_processors.auth

auth()

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

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

django.template.context_processors.debug

debug()

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

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

django.template.context_processors.i18n

i18n()

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

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

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

django.template.context_processors.media

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

django.template.context_processors.static

static()

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

django.template.context_processors.csrf

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

django.template.context_processors.request

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

django.template.context_processors.tz

tz()

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

django.contrib.messages.context_processors.messages

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

Написание собственного контекстного процессора

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

Пользовательские обработчики контекста можно найти в любом месте кода. Все, что требуется Django, - это чтобы параметр 'context_processors' настройки TEMPLATES (или параметр context_processors движка, Engine если вы его используете напрямую) содержал путь к пользовательскому процессору.

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

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

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 использует загрузчик шаблонов на основе файловой системы, но есть также несколько других загрузчиков шаблонов, которые знают, как загружать шаблоны из других источников.

Некоторые из этих зарядных устройств по умолчанию отключены, но вы можете включить их, добавив параметр 'loaders' в свой двигатель DjangoTemplates при настройке TEMPLATES или передав параметр loaders в Engine . loaders должен содержать список строк или кортежей, где каждый элемент представляет класс загрузчика шаблона. Вот загрузчики шаблонов, которые предлагает Django:

django.template.loaders.filesystem.Loader

класс 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

класс app_directories.Loader

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

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

Например, с этой настройкой:

INSTALLED_APPS = ['myproject.polls', 'myproject.music']

... get_template('foo.html') искать foo.html в этих каталогах в следующем порядке:

  • /chemin/vers/myproject/polls/templates/
  • /chemin/vers/myproject/music/templates/

… И воспользуйся первым, который найдет.

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

класс cached.Loader

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

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

Этот загрузчик активируется автоматически, если OPTIONS['loaders'] он не определен и OPTIONS['debug'] есть False (последний параметр по умолчанию содержит значение DEBUG ).

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

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

Заметка

Все встроенные теги шаблонов Django можно без проблем использовать с "кешированным" загрузчиком, но если вы используете настраиваемые теги шаблонов из внешних пакетов или написали сами, необходимо убедиться, что Реализация объектов Node каждого тега соблюдает параллелизм («потокобезопасный»). Для получения дополнительной информации см. Подсказки о параллелизме потоков в тегах шаблонов .

django.template.loaders.locmem.Loader

класс 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() .

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

класс Loader

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

get_template_sources( имя_шаблона )

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

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

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

get_contents( происхождение )

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

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

get_template( template_name , skip = None )

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

Необязательный параметр skip - это список источников, которые следует игнорировать при расширении шаблонов. Это позволяет распространять шаблоны на другие одноименные шаблоны. Еще одна полезность - избежать ошибок рекурсии.

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

Создание собственного зарядного устройства

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

Источник шаблона

У шаблонов есть атрибут, origin содержащий атрибуты, зависящие от источника, из которого они были загружены.

classOrigin ( name , template_name = None , loader = None )
name

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

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

template_name

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

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

loader

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

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

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

Copyright ©2020 All rights reserved