
Предыдущая часть.
Django предоставляет мощный и удобный API для загрузки шаблонов из файловой системы, цель которого — избавиться от избыточного кода в в вызовах шаблонов и в самих шаблонах.
Для того, что бы использовать этот API — вы должны указать фреймворку, где именно он должен искать файлы шаблонов. Сделать это можно в файле настроек вашего проекта — settings.py, который уже упоминался в первой главе, когда мы рассматривали настройку URLconf и параметр 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, например:
TEMPLATE_DIRS = (
'/var/www/django/example/templates'
)
Несколько моментов, которые надо помнить:
-
Вы можете указать любую директорию, главное что бы она и файлы шаблонов в ней были доступны на чтение вашему веб-серверу. Если вы не можете придумать подходящую — то мы бы рекомендовали вам создать директорию
templatesв каталоге вашего проекта. -
Если параметр
TEMPLATE_DIRSсодержит только один каталог — не забудьте добавить запятую после указания пути.Плохой вариант:
# Missing comma! TEMPLATE_DIRS = ( '/home/django/mysite/templates' )
Хороший вариант:
# Comma correctly in place. TEMPLATE_DIRS = ( '/home/django/mysite/templates', )
Причина этого заключается в том, что для Python необходимо наличие запятых, что бы он мог отличить кортеж от выражений в скобках.
-
Если вы пользуетесь Windows — добавляйте имя диска и используйте Unix-like косые, вместо обратных:
TEMPLATE_DIRS = ( 'C:/www/django/templates', )
-
Лучше всего использовать полные пути от корня вашей файловой системы. Но если вы хотите иметь более гибкую систему — вы можете использовать тот факт, что файл настроек Django — это простой файл Python, и вы можете указать путь к директории шаблонов динамически, например так:
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates').replace('\','/'), )
В этом примере используйется специальная переменная Python
__file__, которая указывает на файл, из которого она вызывается. Тут берётся путь к директории, в которой находится файлsettings.py(os.path.dirname), к нему добавляетсяtemplatesс помощью кросс-платформенной функции (os.path.join), затем все обратные слеши меняются на прямые (на случай использования под Windows).Так как вы теперь немного в курсе использования кода Python в файле настроек — мы должны предупредить вас, что необходимо быть очень осторожным и избегать ошибок Python в нём. Если вы допустите синтаксическую или другую ошибку — ваш сайт упадёт.
Теперь, когда вы настроили TEMPLATE_DIRS, можно изменить само представление на использование системы загрузки шаблонов Django вместо того, что бы вписывать путь к шаблону прямо в код.
Вернёмся к нашему представлению current_datetime, и изменим его так:
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse, Http404
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = get_template('timetemplate.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
В этом примере мы используем функцию django.template.loader.get_template() вместо того, что бы загружать файл шаблона вручную. Функция get_template() принимает имя шаблона первым аргументом, определяет где хранятся шаблоны в файловой системе, открывает этот файл и возвращает скомилированный объект Template.
В нашем примере используется файл шаблона timetemplate.html, но его расширение может быть любым, не обязательно .html. Вы можете указать любое другое подходящее вам расширение — или не указывать его вообще.
Что бы определить расположение файла шаблона в файловой системе, get_template() совмещает директорию шаблонов из настройки TEMPLATE_DIRS и имя шаблона, переданное этой функции. Например, если ваш TEMPLATE_DIRS указан в /var/www/django/example/templates, то функция get_template() будет искать файл /var/www/django/example/templates/timetemplate.html.
Если get_template() не сможет найти файл с заданным именем — она вызове исключение TemplateDoesNotExist. Вот как он выглядит:
Эта страница схожа с той, которую мы рассматривали в статье Django Book: страница ошибки Django, с одним дополнительным полем информации — блок «Template-loader postmortem». В нём описывается — какой именно шаблон Django пытался загрузить и детали неудачной попытки (например — «File does not exist»). Она окажет неоценимую помощь во время поиска причины, по которой шаблон не загружается.
Содержание
render()
Мы показали вам, как загрузить шаблон, заполнить Context и вернуть объект HttpResponse с результатом рендеринга шаблона. Мы оптимизировали этот процесс с использованием функции get_template() вместо того, что указывать файл в коде напрямую. Однако, нам всё ещё требуется много печатать, что бы выполнить все эти действия.
Django предоставляет возможность уменьшить все эти действия — загрузить шаблон, выполнить рендеринг и вернуть HttpResponse — всего одной строкой кода.
Эта возможность — функция с именем render() из модуля django.shortcuts. В основном вы будете пользоваться именно ей, вместо того, что бы выполнять все эти действия вручную — по крайней мере, если ваш работодатель не платит вам за количество строк кода, который вы пишете.
Вот наша функция current_datetime, переписанная с использованием render():
from django.shortcuts import render
import datetime
def current_datetime(request):
now = datetime.datetime.now()
return render(request, 'timetemplate.html', {'current_date': now})
Чувствуете разницу? Давайте посмотрим какие изменения мы сделали:
- Мы больше не выполняем импорт
get_template,Template,ContextиHttpResponse. Вместо этого мы импортируемdjango.shortcuts.render.import datetimeостаётся. - Внутри функции
current_datetimeмы оставляем вычисление значения переменнойnow, но убираем загрузку шаблона, создание контекста, рендеринг шаблона и созданиеHttpResponse— теперь всем этим занимается функцияrender().
Первый аргумент для render() — это request, второй — имя шаблона. Третий аргумент, если указан — это словарь для создания контекста этого шаблона. Если его не указать — render() будет использовать пустой словарь.
Вложенные каталоги в get_template()
Может быть неудобно хранить все ваши шаблоны в одной директории. Возможно, вы захотите поместить некоторые шаблоны во вложенные каталоги вашей директории templates — и это можно сделать. Мы даже рекомендуем вам так поступать — некоторые более продвинутые возможности Django будут ожидать такого.
Хранить шаблоны во вложенных каталогах очень просто. В вашем вызове функции get_template() просто укажите имя директории, слеш и имя файла шаблона, например так:
t = get_template('dateapp/current_datetime.html')
Так как render() — это лишь маленькая обёртка вокруг get_template() — вы можете сделать то же со вторым аргументом ей, например:
return render(request, 'dateapp/current_datetime.html', {'current_date': now})
Нет никаких ограничений на глубину вложенности каталогов.
Примечание
Пользователи Windows — помните про использование прямых слешей вместо обратных, так как get_template() ожидает получить их в Unix-like виде.
Тег шаблонов include
Теперь, когда мы в целом разобрались с системой загрузки шаблонов, мы можем рассказать вам о встроенном теге {% include %}, который даст вам дополнительные преимущества. Он позволяет включать содержимое одного шаблона в другой. Аргументом ему передаётся имя шаблона, который необходимо включить в основной шаблон, а имя может быть задано либо с помощью переменной — либо в виде строки, заключённой в кавычки. Каждый раз, когда вам приходится использовать один и тот же код в шаблонах — старайтесь пользоваться {% include %}.
В этих двух примерах выполняется добавление шаблона nav.html. Оба примера одинаковы — вы можете использовать как одинарные, так и двойные кавычки:
{% include 'nav.html' %}
{% include "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 — она будет доступна из вложенного шаблона.
Если при использовании тега {% include %} заданный шаблон не будет найден — Django поступит следующим образом:
- Если
DEBUGвключен — будет выдана ошибка TemplateDoesNotExist на странице ошибок Django; - Если
DEBUGвыключен — никаких сообщений не будет, а на месте тега будет пустое место.
Продолжение и последняя часть второй главы — Django Book: наследование в шаблонах.





