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

Этот раздел описывает систему шаблонов Django с технической стороны – как она работает и как расширить её. Если вы ищите просто описание синтаксиса шаблонов, смотрите Язык шаблонов Django.

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

Основы

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

Блочный тег – просто символ в шаблоне, который что-то означает.

Это определение такое неточное намеренно. Например, блочный тег может выводить текст, работать как условный оператор (“if” или “for” для циклов), получать данные из базы данных или загружать другие шаблонные теги.

Блочные теги выделены "{%" и "%}".

Пример шаблона с блочными тегами:

{% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %}

Переменная – это символ в шаблоне, который выводит какое-то значение.

Переменные выделены "{{" и "}}".

Пример шаблона с переменными:

My first name is {{ first_name }}. My last name is {{ last_name }}.

Контекст – это структура, которая содержит соответствия “название переменной” -> “значение переменной” и передается в шаблон.

Шаблон рендерит контекст, заменяет переменные значениями из контекста и выполняет все блочные теги.

Использование системы шаблонов

class Template

Система шаблонов в Python работает в два этапа:

  • Сначала вы компилируете код шаблона в объект Template.

  • Затем вызываете метод render() объекта Template, передав контекст.

Компилирование строки

Самый простой способ создать объект Template – создать экземпляр класса. Класс находится в django.template.Template. Конструктор принимает один аргумент – “сырой” код шаблона:

>>> from django.template import Template
>>> t = Template("My name is {{ my_name }}.")
>>> print(t)
<django.template.Template instance>

За кулисами

Система парсит код шаблона один раз – когда вы создаете объект Template. Результат сохраняется в объекте как структура “нодов”, чтобы повысить производительность системы шаблонов.

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

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

render(context)

Скомпилировав объект Template, вы можете отрендерить с его помощью контекст, или несколько контекстов. Класс Context находится в django.template.Context, конструктор принимает два (необязательных) аргумента:

Вызовите метод render() объекта Template с контекстом, чтобы “выполнить” шаблон:

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

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

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

Переменные

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

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

  • Поиск в словаре. Например: foo["bar"]

  • Поиск атрибута. Например: foo.bar

  • Поиск в списке. Напрмиер: foo[bar]

Обратите внимание, “bar” в выражении {{ foo.bar }} будет интепретировано как строка “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. В таком случае переменная будет отрендерена как пустая строка. Например:

    >>> t = Template("My name is {{ person.first_name }}.")
    >>> class PersonClass3:
    ...     def first_name(self):
    ...         raise AssertionError("foo")
    >>> p = PersonClass3()
    >>> t.render(Context({"person": p}))
    Traceback (most recent call last):
    ...
    AssertionError: foo
    
    >>> class SilentAssertionError(Exception):
    ...     silent_variable_failure = True
    >>> class PersonClass4:
    ...     def first_name(self):
    ...         raise SilentAssertionError
    >>> p = PersonClass4()
    >>> t.render(Context({"person": p}))
    "My name is ."
    

    Обратите внимание, django.core.exceptions.ObjectDoesNotExist, который является родительским для всех ошибок DoesNotExist в ORM, содержит silent_variable_failure = True. По этому, если вы используете объекты модели в шаблонах, исключение DoesNotExist будет проигнорировано.

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

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

    Хороший пример – метод delete() модели. Нельзя позволять шаблонам выполнять следующее:

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

    Чтобы избежать этого, укажите атрибут alters_data в функции или методе. Шаблон не будет вызывать переменную, если значение содержит alters_data=True, и будет использовать значение настройки TEMPLATE_STRING_IF_INVALID. Встроенные методы delete() и save() модели содержат атрибут alters_data=True. Например:

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

Как обрабатываются неправильные переменные

Если переменная не найдена в шаблоне, будет использоваться значение настройки TEMPLATE_STRING_IF_INVALID, равной по умолчанию '' (пустая строка).

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

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

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

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

Хотя TEMPLATE_STRING_IF_INVALID и полезная для отладки, лучше не менять её по умолчанию и использовать только при необходимости локально.

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

Как правило TEMPLATE_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

class Context

Обычно при создании объекта Context сразу передается словарь со всеми переменными. Но вы можете менять содержимое объекта Context и после его инициализации, использую стандартный API словарей:

>>> from django.template import Context
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
''
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
Context.pop()
Context.push()
exception 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
Добавлено в Django 1.7.

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'
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'

Использовать Context, как стек, удобно в собственных тегах. Ниже мы покажем пример.

Context.flatten()
Добавлено в Django 1.7.

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

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

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

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

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

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

Классы наследники Context: RequestContext

class RequestContext

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

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

Еще одно отличие – он автоматически добавляет различные переменные в соответствии с настройкой TEMPLATE_CONTEXT_PROCESSORS.

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

("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.tz",
"django.contrib.messages.context_processors.messages")

Кроме этого RequestContext всегда использует django.core.context_processors.csrf. Этот процессор контекста используется для безопасности админкой и другими встроенными приложениями. Чтобы исключить его случайное отключение, он захардкоден и не может быть выключен с помощью настройки TEMPLATE_CONTEXT_PROCESSORS.

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

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

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

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

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

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

def some_view(request):
    # ...
    c = RequestContext(request, {
        'foo': 'bar',
    }, [ip_address_processor])
    return HttpResponse(t.render(c))

Примечание

Если вы используете встроенную в Django функцию render_to_response() для рендеринга шаблона, в шаблон будет передан экземпляр Context (не RequestContext). Чтобы использовать RequestContext, передайте третьим аргументом в render_to_response() экземпляр RequestContext. Например:

from django.shortcuts import render_to_response
from django.template import RequestContext

def some_view(request):
    # ...
    return render_to_response('my_template.html',
                              my_data_dictionary,
                              context_instance=RequestContext(request))

Еще можно использовать функцию render(), которая работает аналогично render_to_response(), но использует RequestContext.

Обратите внимание, переменные из передаваемого словаря (my_data_dictionary в нашем примере) будут иметь приоритет над переменными процессоров контекста или RequestContext.

Вот список процессоров контекста по умолчанию:

django.contrib.auth.context_processors.auth

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

  • user – объект auth.User текущего авторизованного пользователя или объект AnonymousUser, если пользователь не авторизованный).

  • perms – объект django.contrib.auth.context_processors.PermWrapper, которые содержит права доступа текущего пользователя.

django.core.context_processors.debug

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

  • debugTrue. Вы можете использовать эту переменную, чтобы определить DEBUG режим в шаблоне.

  • sql_queries – список словарей {'sql': ..., 'time': ...}, который содержит все SQL запросы и время их выполнения, которые были выполнены при обработке запроса. Список отсортирован в порядке выполнения SQL запроса.

django.core.context_processors.i18n

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

  • LANGUAGES – значение настройки LANGUAGES.

  • LANGUAGE_CODErequest.LANGUAGE_CODE, если существует. Иначе значение LANGUAGE_CODE.

Смотрите Интернационализация и локализация.

django.core.context_processors.media

Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в RequestContext будет добавлена переменная MEDIA_URL, которая содержит значение MEDIA_URL.

django.core.context_processors.static

static()

Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в RequestContext будет добавлена переменная STATIC_URL, которая содержит значение STATIC_URL.

django.core.context_processors.csrf

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

django.core.context_processors.request

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

django.contrib.messages.context_processors.messages

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

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

Была добавлена переменная DEFAULT_MESSAGE_LEVELS.

Как создать свой процессор контекста

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

Код процессора может находится где угодно. Главное не забыть указать его в настройке TEMPLATE_CONTEXT_PROCESSORS.

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

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

Django ищет каталоги с шаблонами в соответствии с настройками загрузки шаблонов (смотрите “Типа загрузчиков” (FIXME) ниже). Самый простой способ – указать каталоги с шаблонами в настройке TEMPLATE_DIRS.

Настройка TEMPLATE_DIRS

Вы можете указать Django каталоги с шаблонами через настройку TEMPLATE_DIRS в файле настроек проекта. Настройка должна содержать список или кортеж полных путей к каталогам. Например:

TEMPLATE_DIRS = (
    "/home/html/templates/lawrence.com",
    "/home/html/templates/default",
)

Шаблоны могут находиться где угодно, главное, чтобы у Web-сервера были права на чтение. Расширение файла может быть любым, .html или .txt, или вообще без расширения.

Обратите внимание, пути должны быть Unix-стиле, даже для Windows (то есть использовать /).

Python API

django.template.loader содержит две функции для загрузки шаблонов с файла:

get_template(template_name[, dirs])

get_template возвращает скомпилированный шаблон (объект Template) для указанного названия шаблона. Если шаблон не найден, будет вызвано исключение django.template.TemplateDoesNotExist.

Чтобы переопределить настройку TEMPLATE_DIRS, используйте аргумент dirs. Аргумент dirs может быть списком или кортежем.

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

Был добавлен аргумент dirs.

select_template(template_name_list[, dirs])

select_template похож на get_template, но принимает список шаблонов. Возвращает первый доступный шаблон из списка.

Чтобы переопределить настройку TEMPLATE_DIRS, используйте аргумент dirs. Аргумент dirs может быть списком или кортежем.

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

Был добавлен аргумент dirs.

Например, для get_template('story_detail.html'), при настройке TEMPLATE_DIRS из примера выше, Django будет проверять такие файлы в следующем порядке:

  • /home/html/templates/lawrence.com/story_detail.html
  • /home/html/templates/default/story_detail.html

Для select_template(['story_253_detail.html', 'story_detail.html']), Django будет искать:

  • /home/html/templates/lawrence.com/story_253_detail.html
  • /home/html/templates/default/story_253_detail.html
  • /home/html/templates/lawrence.com/story_detail.html
  • /home/html/templates/default/story_detail.html

Как только Django найдет шаблон, поиск будет остановлен.

Совет

Вы можете использовать select_template() для супер-гибкой структуры шаблонов. Например, если у вас есть новости и вы хотите для некоторых использовать собственный шаблон, используйте следующий код select_template(['story_%s_detail.html' % story.id, 'story_detail.html']). Такой подход позволит использовать собственный шаблон для некоторых новостей и шаблон по умолчанию для всех остальных.

Использование под-каталогов

Вы можете организовать хранение шаблонов в под-каталогах в каталоге шаблонов и мы рекомендуем использовать такой подход. Существует неписанное соглашение разделять шаблоны по под-каталогам для каждого приложения Django.

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

Чтобы загрузить шаблон из под-каталога, используйте слеш:

get_template('news/story_detail.html')

Для настройки TEMPLATE_DIRS из примера выше этот вызов get_template() будет искать следующие шаблоны:

  • /home/html/templates/lawrence.com/news/story_detail.html
  • /home/html/templates/default/news/story_detail.html

Типы загрузчиков

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

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

django.template.loaders.filesystem.Loader

class filesystem.Loader

Загружает шаблоны с файловой системы в соответствии с настройкой TEMPLATE_DIRS. Включен по умолчанию.

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.

Загрузчик включен по умолчанию.

django.template.loaders.eggs.Loader

class eggs.Loader

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

Загрузчик выключен по умолчанию.

django.template.loaders.cached.Loader

class cached.Loader

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

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

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

TEMPLATE_LOADERS = (
    ('django.template.loaders.cached.Loader', (
        'django.template.loaders.filesystem.Loader',
        'django.template.loaders.app_directories.Loader',
    )),
)

Примечание

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

Загрузчик выключен по умолчанию.

Django использует загрузчики шаблонов в порядке указанном в настройке TEMPLATE_LOADERS. Загрузчики используются пока один из них не найдет шаблон.

Расположение шаблона

Добавлено в Django 1.7.

При TEMPLATE_DEBUG равном True объект шаблона содержит атрибут origin, который указывает на расположение шаблона.

class loader.LoaderOrigin

Шаблоны, загруженные с помощью загрузчика шаблонов, будут использовать класс django.template.loader.LoaderOrigin как значение этого атрибута.

name

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

loadname

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

class StringOrigin

Шаблоны созданные классом Template будут использовать класс django.template.StringOrigin.

source

Строка, которая использовалась для создания шаблона.

Функция render_to_string

loader.render_to_string(template_name, dictionary=None, context_instance=None)

Для удобства загрузки и ренедеринга шаблон Django предоставляет функцию, которая упрощает это процесс: render_to_string() из django.template.loader. Она загружает шаблон, рендерит его и возвращает строку:

from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})

render_to_string принимает один обязательный аргумент – template_name, который указывает название шаблона, который необходимо загрузить и отрендерить (или список шаблонов, Django будет использовать первый найденный шаблон) – и два необязательных:

dictionary

Словарь с переменными, который будет добавлен в контекст при рендеринге. Можно передавать как второй позиционный аргумент.

context_instance

Экземпляр Context или под-класса (например экземпляр RequestContext), который будет использоваться как контекст. Можно передавать как третий позиционный аргумент.

Смотрите также render_to_response(). Она вызывает render_to_string и передает в HttpResponse, который можно вернуть из представления.

Настройка системы шаблонов в стороннем приложении

Примечание

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

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

Для этого вы должны использовать явную настройку, описанную в Using settings without setting DJANGO_SETTINGS_MODULE. Просто импортируйте необходимый модуль системы шаблонов, затем, перед использованием какого либо функционала, вызовите django.conf.settings.configure() с необходимыми настройками. В первую очередь вам следует указать TEMPLATE_DIRS (если вы хотите использовать загрузчики шаблонов), DEFAULT_CHARSET (если utf-8 по умолчанию вас не устраивает) и TEMPLATE_DEBUG. Если вы планируете использовать тег url, необходимо указать ROOT_URLCONF. Все доступные настройки указаны в разделе о настройках Django, в первую очередь обратите внимание на настройки, которые начинают с префикса TEMPLATE_.

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

Классы Template и Loader предоставляют простой API для загрузки и рендеринга шаблонов. Реализовав этот API вы можете использовать сторонние системы шаблонов, например Jinja2 или Cheetah. Это позволяет использовать различные языки разметки шаблон вместе с полезным функционалом Django, например объекты Context и функцию render_to_response().

Главный компонент системы шаблонов Django – класс Template. Этот класс предоставляет очень простой интерфейс: его конструктор принимает строку шаблона, а метод render() принимает объект :class:`~django.template.Context`и возвращает отрендеренный шаблон.

Предположим мы используем систему шаблонов, которая предоставляет объект Template с методом render(), который принимает словарь вместо объекта Context. Мы может создать простой класс-обертку, который реализует интерфейс класса Template Django:

import some_template_language
class Template(some_template_language.Template):
    def render(self, context):
        # flatten the Django Context into a single dictionary.
        context_dict = {}
        for d in context.dicts:
            context_dict.update(d)
        return super(Template, self).render(context_dict)

Это все что необходимо, чтобы наш класс Template работал с загрузкой и рендерингом шаблонов Django!

Следующий шаг – создать класс Loader, который возвращает экземпляры нашего класса, а не стандартного Template. Наш класс Loader должен наследоваться от django.template.loader.BaseLoader и переопределять метод load_template_source(), который принимает аргумент template_name, загружает шаблон с файловой системы (или другого источника), и возвращает кортеж: (template_string, template_origin).

Метод load_template() класса Loader загружает содержимое шаблона, используя load_template_source(), создает экземпляр Template с этим содержимым, и возвращает кортеж: (template, template_origin). Т.к. этот метод создает экземпляр Template, нам необходимо переопределить его, чтобы использовать наш класс. Мы может наследоваться от django.template.loaders.app_directories.Loader, чтобы использовать возможности его метода load_template_source():

from django.template.loaders import app_directories
class Loader(app_directories.Loader):
    is_usable = True

    def load_template(self, template_name, template_dirs=None):
        source, origin = self.load_template_source(template_name, template_dirs)
        template = Template(source)
        return template, origin

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