Главная | Архив новостей | Общение | Площадка | Примеры OpenID
Хостинг Django от «Джино»
Оглавление

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

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.

Рисунок 4.1. Страница с ошибкой показывающей, что шаблон не найден

Страница с ошибкой показывающей, что шаблон не найден


Эта страница с ошибкой похожа на такую же, которую мы рассматривали в главе «Представления и привязки URL», только одна вещь тут новая — отладочная информация: секция «Template-loader postmortem». Эта информация неоценима при отладке ошибок загрузки шаблона.

Далее, создадим файл /home/django/templates/current_datetime.html в вашем каталоге с шаблонами, с помощью кода:

<html><body>It is now {{ current_date }}.</body></html>

Обновите страницу в вашем браузере и вы увидите результат обработки шаблона.

render_to_response()

Мы показали вам как загружать шаблон, заполнять 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() должно быть имя используемого шаблона. Вторым аргументом, если он есть, должен быть словарь, используемый при создании контекста для этого шаблона. Если вы не предоставите второй аргумент, функция будет использовать пустой словарь.

Трюк с locals()

Рассмотрим последнюю инкарнацию функции current_datetime:

def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

Постоянно вы будете ловить себя на том, что вы вычисляете значения, сохраняете их в переменных (см. now в предыдущем примере) и отправляете эти переменные в шаблон. Особо ленивые разработчики должны отметить, что это немного излишне назначать имена временным переменным и шаблонным переменным. Это не только излишне, но и требует много набора на клавиатуре.

Таким образом, если вы один из таких ленивых разработчиков и вам нравится краткий код, вы можете воспользоваться встроенной в Python функцией locals(). Она возвращает словарь, хранящий все локальные переменные и их соответствующие значения (речь идёт о всех переменных, определённых в текущей области видимости). Следовательно, предыдущую функцию представления можно переписать так:

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())

Здесь, вместо ручного ввода контекстного словаря, как это было раньше, вы передали значение функции locals(), которое содержало все переменные определённые в этой точке выполнения функции. Как результат, мы переименовали переменную now в current_date, потому что это то имя, которое шаблон ожидает. В этом примере locals() не предлагает значительного удобства, но эта методика может сохранить вам время, если вы используете несколько шаблонных переменных или если вы ленивы.

Следует обратить внимание при использовании locals() на то, что она включает в результат каждую локальную переменную. Это может быть не совсем то, что вам нужно. В предыдущем примере, locals() также включает request. Важно ли это для вас, зависит от вашего приложения и вашего уровня перфекционизма.

Подкаталоги в get_template()

Может стать неудобно хранить все шаблоны в одном каталоге. Вам может понадобиться хранить шаблоны в подкаталогах вашего каталога шаблонов, это нормально. Действительно, мы рекомендуем делать так. Более продвинутые особенности Django (такие как общая система представлений, которая будет описана в главе «Генерация данных, отличных от HTML») ожидают такое расположение шаблонов по умолчанию.

Хранение шаблонов в подкаталогах несложное занятие. В вашем вызове get_template(), просто включите имя подкаталога и слэш перед именем шаблона, вот так:

t = get_template('dateapp/current_datetime.html')

Так как render_to_response() является небольшой обёрткой к get_template(), вы можете делать то же самое и с первым аргументом функции render_to_response().

Нет ограничений на глубину дерева подкаталогов. Используйте столько сколько нужно.

Замечание

Пользователи Windows должны использовать прямой слэш (/) вместо обратного (\). Функция get_template() ожидает прямые слэши в имени файла с шаблоном.

Шаблонный тег include

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


Увидели ошибку?
Выделите её мышкой и нажмите
Ctrl-Enter
Обработано:
511 49 130 71

Версия книги
1.0 2.0
Версия 2.0 в процессе перевода!

Мой луч
Многообразие света

Полезное
Актуальные вакансии, Python работа для python-разработчиков.


Скачать в формате
CHM от 2 сентября

Заказать PDF файл можно через почту, чат, джаббер. Всего 2WMZ. Содержимое точно соответствует содержимому сайта.
Чем чаще заказываете — тем больше перевожу.

Русская группа

на поддержку перевода
Яндекс Яндекс.Деньги Хочу такую же кнопку
Ускорить процесс перевода!
R130494980980
Z425285133788
E112528079659
U327380922061

Книга помогла реализовать:
Проект «Мой луч»
АРМ УФМС.


Мой вебсайт стоит666 337,31 руб

© 2008-2009 Ruslan Popov @ gmail.com Powered by Django 1.1 beta 1 SVN-11114
Главная | Архив новостей | Общение | Площадка | Примеры OpenID