search
menu
person

NEWS AND UDATES


10:17
Язык шаблонов Джанго для программистов
Этот документ описывает техническую сторону шаблонной системы Джанго, — как она работает и как ее расширять. Если вам нужно справочное руководство по синтаксису языка шаблонов, см. The Django template language.

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

Основы

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

Блочный тег — это часть шаблона, выполняющая какие-либо действия.

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

Теги окружены парами символов "{%" и "%}".

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

{% if is_logged_in %}Вы успешно авторизованы!{% else %}Пожалуйста, авторизуйтесь.{% endif %}
Переменная — это часть шаблона, выводящая некоторое значение.

Тег переменной заключен в пары символов "{{" и "}}".

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

My first name is {{ first_name }}. My last name is {{ last_name }}.
Контекст — это отображение "имя переменной" -> "значение переменной", передаваемое в шаблон.

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

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

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

Сначала исходный код шаблона компилируется в объект 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, после чего в целях улучшения быстродействия шаблон хранится во внутреннем представлении (в виде «узлов»).

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

Словарь, отображающий имена переменных в их значения.
Название текущего приложения, используемое для разрешения URL в пространстве имен. Если вы не используете пространства имен для URL, этот параметр не требуется.
Вызов метода render() объекта Template с заданным контекстом «заполняет» шаблон:

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

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

>>> c = Context({"my_name": "Dolores"})
>>> t.render©
"My name is Dolores."
Имена переменных могут содержать буквы латинского алфавита (A-Z), цифры (0-9), знаки подчеркивания и точки.

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

среди ключей словаря, например: foo["bar"]
среди атрибутов объекта, например: foo.bar
вызывая метода объекта: foo.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."

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

>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render©
"The first stooge in the list is Larry."
Поиск среди методов объекта несколько сложнее других вариантов поиска, здесь нужно помнить следующее:

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

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

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

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

Сейчас я удалю эти важные данные. {{ data.delete }}
Во избежание такого поведения, определите атрибут метода alters_data. Шаблонизатор не будет вызывать метод, если у него имеется атрибут alters_data=True. Динамически генерируемые методы моделей delete() и save() имеют alters_data=True автоматически. Пример:

def sensitive_function(self):
self.database_record.delete()
sensitive_function.alters_data = 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 значение, отличное от '', вас ждут проблемы с обработкой этих шаблонов.

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

>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
''
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
Объект Context является стековым, то есть вы можете использовать его методы push() и pop(). Если вы попытаетесь вызвать pop() больше возможного, это приведет к исключению django.template.ContextPopException:

>>> c = Context()
>>> c['foo'] = 'первый уровень'
>>> c.push()
>>> c['foo'] = 'второй уровень'
>>> c['foo']
'второй уровень'
>>> c.pop()
>>> c['foo']
'первый уровень'
>>> c['foo'] = 'перезаписано'
>>> c['foo']
'перезаписано'
>>> c.pop()
Traceback (most recent call last):
...
django.template.ContextPopException
Использование Context в качестве стека бывает полезно в некоторых пользовательских шаблонных тегах (подробности чуть ниже).

Наследование от Context: объект RequestContext
В Джанго есть специальный подкласс 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.contrib.messages.context_processors.messages")
Добавлено в Джанго 1.2: В дополнение к этим процессорам, RequestContext всегда использует процессор 'django.core.context_processors.csrf'. Этот контекстный процессор связан с вопросами безопасности, его требует приложение админки и другие приложения. На случай непреднамеренных изменений в конфигурации, он напрямую подключается в коде Джанго и не может быть отключен путем изменения параметра TEMPLATE_CONTEXT_PROCESSORS.
Добавлено в Джанго 1.2: Включен контекстный процессор 'messages'. Подробнее см. в документации по сообщениям.
Изменено в Джанго 1.2: Контекстный процессор авторизации перемещен из старого расположения django.core.context_processors.auth в django.contrib.auth.context_processors.auth.
Контекстные процессоры применяются по очереди. Это значит, что если первый процессор добавляет переменную в контекст, а следующий процессор добавляет переменную с таким же именем, то второе значение сотрет первое. Описания встроенных процессоров Джанго приведены ниже.

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

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©)
Примечание
Если вы используете шорткат render_to_response() для передачи в шаблон содержимого словаря, по умолчанию шаблон получает объект Context (а не RequestContext). Для использования в шаблоне объекта RequestContext передавайте его в render_to_response() в необязательном третьем аргументе, см. пример:

def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Далее приведены описания встроенных контекстных процессоров Джанго:

django.contrib.auth.context_processors.auth
Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в каждом объекте RequestContext будут определены следующие три переменные:

user — экземпляр auth.User, представляющий текущего залогиненного пользователя (либо экземпляр AnonymousUser, если посетитель не залогинился).
messages — список сообщений (в виде строк), установленных через модуль сообщений.
perms — экземпляр django.core.context_processors.PermWrapper, представляющий привилегии текущего пользователя.
Изменено в Джанго 1.2: Данный контекстный процессор перемещен из django.core.context_processors.auth в свое текущее местоположение.
Изменено в Джанго 1.2: До версии 1.2 переменная messages обеспечивала «ленивый» доступ к методу user.get_and_delete_messages(). Теперь она может включать все сообщения, добавленные через модуль сообщений.
django.core.context_processors.debug
Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в каждом объекте RequestContext будут определены следующие две переменные (но только если параметр DEBUG равен True и IP-адрес запроса, находящийся в request.META['REMOTE_ADDR'], перечислен в параметре INTERNAL_IPS):

debug — равна True. Можно использовать в шаблонах для проверки режима DEBUG.
sql_queries — список словарей вида {'sql': ..., 'time': ...}, преставляющих каждый SQL-запрос (query), совершенный во время запроса (request) к моменту использования этой переменной, с указанием времени его выполнения. Список упорядочен по тексту запроса.
django.core.context_processors.i18n
Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в каждом объекте RequestContext будут определены следующие две переменные:

LANGUAGES — значение параметра LANGUAGES.
LANGUAGE_CODE — значение request.LANGUAGE_CODE, если определено, иначе значение параметра LANGUAGE_CODE.
Подробнее см. Internationalization and localization.

django.core.context_processors.media
Добавлено в Джанго 1.0: См. примечания к выпуску
Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в каждом объекте RequestContext будет определена переменная MEDIA_URL со значением параметра MEDIA_URL.

django.core.context_processors.csrf
Добавлено в Джанго 1.2: См. примечания к выпуску
Этот процессор добавляет токен, требующийся для шаблонного тега csrf_token для защиты от межсайтовой подделки запросов.

django.core.context_processors.request
Если TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, в каждом объекте RequestContext будет определена переменная request, содержащая текущий объект HttpRequest. Имейте в виду, что по умолчанию этот процессор не включен; вам нужно будет активировать его.

django.contrib.messages.context_processors.messages
Если список TEMPLATE_CONTEXT_PROCESSORS содержит данный процессор, то в каждый объект RequestContext будет добавлена следующая переменная:

messages — список сообщений (в виде строк), установленных через модель пользователя (с использованием метода user.message_set.create) либо через модуль сообщений.
Добавлено в Джанго 1.2: Эта переменная для шаблонного контекста ранее определялась в контекстном процессоре 'auth'. Для обратной совместимости контекстный процессор 'auth' будет определять переменную messages до Джанго 1.4. Если вы используете эту переменную, ваш проект будет работать с любым из этих процессоров (и даже с обоими вместе), однако рекомендуется добавить django.contrib.messages.context_processors.messages в список процессоров для подготовленности к будущим обновлениям.
Пользовательские контекстные процессоры
Контекстный процессор имеет очень простой интерфейс: это обычная функция, принимающая объект HttpRequest в качестве единственного аргумента и возвращающая словарь, который будет добавлен в контекст шаблона. Контекстный процессор обязан возвращать словарь.

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

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

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

Параметр TEMPLATE_DIRS
Для указания на ваши папки с шаблонами используйте параметр TEMPLATE_DIRS. Он представляет собой список или кортеж строк с полными путями к папке шаблонов. Пример:

TEMPLATE_DIRS = (
"/home/html/templates/lawrence.com",
"/home/html/templates/default",
)
Шаблоны могут располагаться где угодно, лишь бы веб-сервер имел доступ к указанным папкам и шаблонам. Расширение файлов шаблонов может быть любым: .html, .txt, или вообще отсутствовать.

Имейте в виду, что пути должны быть указаны с обычным слэшем (в Unix-стиле), даже под Windows.

Шаблоны в коде (Python API)
Джанго может загружать шаблоны из файлов двумя способами:

django.template.loader.get_template(template_name)
get_template возвращает скомпилированный объект Template для шаблона с указанным именем. Если шаблон не существует, вызывает исключение django.template.TemplateDoesNotExist.
django.template.loader.select_template(template_name_list)
Метод select_template аналогичен методу get_template, с той разницей, что принимает список имен шаблонов, возвращая первый существующий из них.
Например, при вызове get_template('story_detail.html') с параметром TEMPLATE_DIRS как указано выше, Джанго будет искать файлы шаблонов в следующем порядке:

/home/html/templates/lawrence.com/story_detail.html
/home/html/templates/default/story_detail.html
При вызове select_template(['story_253_detail.html', 'story_detail.html']), Джанго будет проверять существование следующих шаблонов:

/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
Поиск прекращается, как только найден первый существующий шаблон.

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

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

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

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

Изначально некоторые из этих загрузчиков отключены, включить их можно, отредактировав параметр TEMPLATE_LOADERS. Это должен быть кортеж строк, указывающих на шаблонные загрузчики. В Джанго включены следующие типы загрузчиков:

django.template.loaders.filesystem.Loader
Загружает шаблоны из файлов в папках, явно указанных в TEMPLATE_DIRS. Включен по умолчанию.
django.template.loaders.app_directories.Loader
Загружает шаблоны из файлов в папках Джанго-приложений. Ищет папку templates в каталоге каждого приложения, указанного в параметре INSTALLED_APPS. Если папка существует, ищет шаблоны в ней.

Таким образом вы можете хранить шаблоны вместе со своими приложениями. Кроме того, это позволяет легко распространять Джанго-приложения вместе с соответствующими шаблонами.

К примеру, при параметре:

INSTALLED_APPS = ('myproject.polls', 'myproject.music')
вызов get_template('foo.html') будет искать шаблоны в следующих папках по порядку:

/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Обратите внимание: в целях оптимизации при первом импорте этот загрузчик кэширует список приложений из списка INSTALLED_APPS, у которых есть папка templates.

По умолчанию этот загрузчик включен.

django.template.loaders.eggs.Loader
Аналогичен загрузчику app_directories, но загружает шаблоны не из файлов, а из питоньих яиц :-) (Python eggs).

По умолчанию этот загрузчик выключен.

django.template.loaders.cached.Loader
По умолчанию шаблонная система будет читать и компилировать шаблон при каждом его вызове. Несмотря на то, что шаблонная система Джанго весьма быстра, задержки при чтении и компиляции шаблонов могут выливаться в ощутимые потери.

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

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

TEMPLATE_LOADERS = (
('django.template.loaders.cached.Loader', (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)),
)
Примечание
Все встроенные шаблонные теги Джанго безопасны для использования с кэширующим загрузчиком, но если вы применяете пользовательские теги, входяшие в состав сторонних модулей или написанные вами, вам следует обеспечить безопасность использования объектов Node в многопоточном режиме. Подробнее читайте в разделе безопасность шаблонных тегов в потоках.
По умолчанию этот загрузчик выключен.

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

Метод render_to_string()

Для уменьшения рутинности процедуры загрузки и обработки шаблонов Джанго располагает shortcut-методом 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, содержащий имя нужного шаблона либо список имен шаблонов (в этом случае Джанго использует первый успешно найденный шаблон) — и два необязательных:

dictionary
Словарь для использования в качестве переменных и их значений в контексте шаблона. Также может быть передан как второй позиционный аргумент.
context_instance
Экземпляр объекта Context или его подкласса (например, экземпляр RequestContext) для использования в качестве контекста шаблона. Также может быть передан как третий позиционный аргумент.
См. также метод render_to_response(): он вызывает render_to_string и помещает результат в объект HttpResponse, который можно непосредственно вернуть в качестве результата функции представления.

Настройка шаблонной системы в качестве отдельного компонента

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

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

Using an alternative template language

Добавлено в Джанго 1.2: См. примечания к выпуску
The Django Template and Loader classes implement a simple API for loading and rendering templates. By providing some simple wrapper classes that implement this API we can use third party template systems like Jinja2 or Cheetah. This allows us to use third-party template libraries without giving up useful Django features like the Django Context object and handy shortcuts like render_to_response().

The core component of the Django templating system is the Template class. This class has a very simple interface: it has a constructor that takes a single positional argument specifying the template string, and a render() method that takes a django.template.context.Context object and returns a string containing the rendered response.

Suppose we're using a template language that defines a Template object with a render() method that takes a dictionary rather than a Context object. We can write a simple wrapper that implements the Django Template interface:

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)
That's all that's required to make our fictional Template class compatible with the Django loading and rendering system!

The next step is to write a Loader class that returns instances of our custom template class instead of the default django.template.Template. Custom Loader classes should inherit from django.template.loader.BaseLoader and override the load_template_source() method, which takes a template_name argument, loads the template from disk (or elsewhere), and returns a tuple: (template_string, template_origin).

The load_template() method of the Loader class retrieves the template string by calling load_template_source(), instantiates a Template from the template source, and returns a tuple: (template, template_origin). Since this is the method that actually instantiates the Template, we'll need to override it to use our custom template class instead. We can inherit from the builtin django.template.loaders.app_directories.Loader to take advantage of the load_template_source() method implemented there:

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
Finally, we need to modify our project settings, telling Django to use our custom loader. Now we can write all of our templates in our alternative template language while continuing to use the rest of the Django templating system.

Источник информации
Просмотров: 5830 | Добавил: django | Рейтинг: 0.0/0
Всего комментариев: 0
dth="100%" cellspacing="1" cellpadding="2" class="commTable">
Имя *: Email:
Код *: