Django предоставляет удобный и мощный API для загрузки шаблонов с диска с целью удаления избыточности в вызовах подгрузки шаблонов и в самих шаблонах.
Для использования этого API сначала требуется указать среде разработки где располагаются шаблоны. Это делать надо в файле конфигурации проекта —
settings.py, как мы
показывали в прошлой главе, когда рассказывали о параметре
ROOT_URLCONF.
Если вы следуете книге, откройте ваш
settings.py и найдите параметр
TEMPLATE_DIRS. По умолчанию, он равен пустому
кортежу, содержащему несколько автоматически сгенерированных
комментариев:
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
Этот параметр указывает механизму шаблонной системы Django пути, по которым следует искать шаблоны. Укажите требуемый каталог, в котором вы будете хранить шаблоны, например так:
TEMPLATE_DIRS = (
'/home/django/mysite/templates',
)
Надо отметить несколько моментов:
Вы можете указать любой каталог, который доступен на чтение пользователю, от которого работает ваш веб сервер. Если вы не можете придумать такое место, мы рекомендуем создать каталог
templatesв каталоге вашего проекта (т.е. в каталогеmysite, который вы создали в главе «Начинаем»).Если ваш параметр TEMPLATE_DIRS содержит только один каталог, не забудьте запятую в конце строки с каталогом шаблонов!
Неправильно:
# Missing comma! TEMPLATE_DIRS = ( '/home/django/mysite/templates' )Правильно:
# Comma correctly in place. TEMPLATE_DIRS = ( '/home/django/mysite/templates', )Дело в том, что Python требует наличия запятой в одноэлементном кортеже, чтобы отличать его от обычного выражения окружённого скобками. На этом обычно попадаются новички.
Если вы используете Windows, включите букву диска и используйте Unix-стиль с прямыми слэшами вместо обратных, вот так:
TEMPLATE_DIRS = ( 'C:/www/django/templates', )Проще всего использовать абсолютные пути (т.е. пути до каталогов, которые начинаются от корня файловой системы). Если вы желаете быть более гибким и независимым в данном вопросе, вы можете воспользоваться тем, что файлы настроек в Django — это всего лишь код на языке Python и содержимое TEMPLATE_DIRS можно изменять динамически, например:
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), )Этот пример использует «волшебную» переменную
__file__, которая автоматически заменяется именем файла модуля Python, в котором располагается данный код. Она получает имя каталога, в котором содержитсяsettings.py(os.path.dirname), соединяет его с templates кроссплатформенным способом (os.path.join) и затем проверяет, что используются только прямые слеши, а обратных нет (в случае Windows).Работая с динамическим Python кодом в файле настроек, следует отметить, что очень важно избегать ошибок в этом коде. Если вы сделаете синтаксическую ошибку или ошибку, которая возникнет во время исполнения кода, ваш сайт не будет работать.
После установки TEMPLATE_DIRS, следующим шагом будет изменение кода представления для использования функциональности Django для загрузки шаблонов, вместо указания путей к шаблонам. Возвращаясь к нашему представлению current_datetime, давайте изменим его следующим образом:
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = get_template('current_datetime.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
В данном примере, мы использовали функцию
django.template.loader.get_template()
вместо ручной загрузки шаблона из файловой системы. Функция
get_template() принимает имя шаблона в
качестве аргумента, производит поиск такого шаблона на файловой
системе, открывает этот файл и возвращает скомпилированный
объект Template.
В данном примере наш шаблон имеет имя
current_datetime.html, но в расширении
.html нет ничего особенного. Вы можете давать
вашим шаблонам любое расширение или вообще не использовать его.
Для того, чтобы определить расположение шаблонов на файловой
системе, get_template() использует
информацию из TEMPLATE_DIRS и переданное имя
шаблона. Например, если параметр TEMPLATE_DIRS
содержит '/home/django/mysite/templates', функция
get_template() будет искать шаблон по пути
/home/django/mysite/templates/current_datetime.html.
Если get_template() не может найти шаблон с
указанным именем, она возвращает исключение
TemplateDoesNotExist. Чтобы посмотреть на него,
снова запустите сервер разработки Django с помощью команды
python manage.py runserver, выполненной в
каталоге проекта. Затем запустите с помощью браузера
представление current_datetime (т.е. перейдите по
ссылке http://127.0.0.1:8000/time/). Предполагая
что настройка DEBUG установлена
True и вы ещё не создали шаблон
current_datetime.html, вы должны увидеть
страницу с ошибкой, на которой выделено исключение
TemplateDoesNotExist.
Эта страница с ошибкой похожа на такую же, которую мы рассматривали в главе «Представления и привязки URL», только одна вещь тут новая — отладочная информация: секция «Template-loader postmortem». Эта информация неоценима при отладке ошибок загрузки шаблона.
Далее, создадим файл
/home/django/templates/current_datetime.html
в вашем каталоге с шаблонами, с помощью кода:
<html><body>It is now {{ current_date }}.</body></html>
Обновите страницу в вашем браузере и вы увидите результат обработки шаблона.
Мы показали вам как загружать шаблон, заполнять
Context и возвращать объект
HttpResponse с обработанным
шаблоном. Мы оптимизировали код, используя
get_template() для загрузки шаблона. Но
вам по-прежнему требуется набирать много кода для выполнения
этих действий. По причине частого использования этой
последовательности действий Django предоставляет более
короткий метод, который позволяет вам выполнять эти действия
одной строкой кода.
Речь идёт о функции render_to_response(),
которая определена в модуле
django.shortcuts. Чаще всего вы будете
использовать render_to_response() вместо
вышеописанных действий, кроме случая когда ваш работодатель
оценивает ваш труд по количеству написанных строк кода.
Ниже представлен старый знакомый пример
current_datetime, использующий функцию
render_to_response():
from django.shortcuts import render_to_response
import datetime
def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})
Какая разница! Пройдёмся по изменениям в коде:
Нам больше не надо импортировать
get_template,Template,ContextилиHttpResponse. Вместо этого, мы импортируем django.shortcuts.render_to_response. Импорт datetime остался без изменений.В функции
current_datetimeмы всё ещё вычисляемnow, но загрузка шаблона, создание контекста, обработка шаблона и создание объектаHttpResponse— обо всём этом заботится функцияrender_to_response(). Так как эта функция возвращает объектHttpResponse, мы просто возвращаем это значение в представление.
Первым аргументом функции
render_to_response() должно быть имя
используемого шаблона. Вторым аргументом, если он есть, должен
быть словарь, используемый при создании контекста для этого
шаблона. Если вы не предоставите второй аргумент, функция
будет использовать пустой словарь.
Может стать неудобно хранить все шаблоны в одном каталоге. Вам может понадобиться хранить шаблоны в подкаталогах вашего каталога шаблонов, это нормально. Действительно, мы рекомендуем делать так. Более продвинутые особенности Django (такие как общая система представлений, которая будет описана в главе «Генерация данных, отличных от HTML») ожидают такое расположение шаблонов по умолчанию.
Хранение шаблонов в подкаталогах несложное занятие. В вашем
вызове get_template(), просто включите
имя подкаталога и слэш перед именем шаблона, вот так:
t = get_template('dateapp/current_datetime.html')
Так как render_to_response() является
небольшой обёрткой к get_template(), вы
можете делать то же самое и с первым аргументом функции
render_to_response().
Нет ограничений на глубину дерева подкаталогов. Используйте столько сколько нужно.
Замечание
Пользователи Windows должны использовать прямой слэш
(/) вместо обратного
(\). Функция
get_template() ожидает прямые слэши в
имени файла с шаблоном.
После того как мы описали механизм загрузки шаблонов, мы можем рассказать о встроенном шаблонном теге, который использует его: {% include %}. Этот тег позволяет вам подключать содержимое другого шаблона. Аргументом тега является путь к подключаемому шаблону. Имя шаблона может быть представлено как переменной, так и строкой, заключённой в двойные или одинарные кавычки. Если вы используете один и тот же код в нескольких шаблонах, рассмотрите возможность использования тега {% include %}, чтобы исключить дублирование кода.
Следующий пример дважды подключает содержимое шаблона
nav.html. Строки примера эквивалентны,
несмотря на разницу используемых кавычек:
{% include 'nav.html' %}
{% include "nav.html" %}
Следующий пример показывает как следует подключать содержимое
шаблона includes/nav.html:
{% include 'includes/nav.html' %}
Следующий пример подключает содержимое шаблона, имя которого
содержится в переменной template_name:
{% include template_name %}
Подобно функции get_template(), имя файла
для шаблона определяется с использованием каталога для
шаблонов из параметра конфигурации
TEMPLATE_DIRS.
Подключенные шаблоны обрабатываются в контексте шаблона, который их подключил. Например, рассмотрим два шаблона:
# mypage.html
<html>
<body>
{% include "includes/nav.html" %}
<h1>{{ title }}</h1>
</body>
</html>
# includes/nav.html
<div id="nav">
You are in: {{ current_section }}
</div>
При обработке шаблона mypage.html с
контекстом, в котором определена переменная
current_section, тогда переменная будет
доступна в «подключенном» шаблоне, как вы могли
ожидать.
Если подключаемый шаблон не существует, Django выполнит одно действие из нижеприведённых:
Если параметр конфигурации DEBUG имеет значение True, вы увидите исключение TemplateDoesNotExist на странице с ошибкой.
Если параметр конфигурации DEBUG имеет значение False, вы не увидите никакой ошибки, просто в месте подключаемого шаблона ничего не отобразится.
| Пред. | Уровень выше | След. |
| Использование шаблонов в представлениях | Начало | Наследование шаблонов |
4 comments | Make a comment
А как передать в render_to_response() несколько переменных?
Второй параметр - словарь.
Глупый вопрос, а что делать, если нет параметров, а только файл шаблона? render_to_response требует параметр.
answer to Nule
Глупый вопрос, а что делать, если нет параметров, а только файл шаблона? render_to_response требует параметр.
Передать пустой словарь.