Для обработки шаблона вам необходим контекст. Обычно это
экземпляр django.template.Context, но в поставку Django также входит специальный подкласс —
django.template.RequestContext, который работает
немного иначе. Класс RequestContext по
умолчанию добавляет группу переменных в контекст шаблона - такие
как объект HttpRequest или информацию о
текущем пользователе.
Используйте RequestContext когда вы не
желаете указывать тот же набор переменных в серии
шаблонов. Например, рассмотрим эти четыре представления:
from django.template import loader, Context
def view_1(request):
# ...
t = loader.get_template('template1.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am view 1.'
})
return t.render(c)
def view_2(request):
# ...
t = loader.get_template('template2.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the second view.'
})
return t.render(c)
def view_3(request):
# ...
t = loader.get_template('template3.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the third view.'
})
return t.render(c)
def view_4(request):
# ...
t = loader.get_template('template4.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the fourth view.'
})
return t.render(c)
Следует отметить, что мы явно не используем
сокращение render_to_response() — мы
вручную загружаем шаблоны, конструируем объекты с контекстом и
обрабатываем шаблоны. Мы делаем так с целью облегчения понимания
вами этих примеров.
Каждое представление принимает три одинаковые переменные,
app, user и
ip_address, для своего шаблона. Неплохо было
бы убрать эту избыточность.
Класс RequestContext и контекстные
процессоры были созданы для решения этой задачи. Контекстные
процессоры позволяют вам указывать ряд переменных, которые будут
устанавливаться автоматически для каждого контекста, без
необходимости их указания в каждом вызове
render_to_response(). Надо лишь
использовать RequestContext вместо
Context при обработке шаблона.
Самый низкоуровневый метод использования контекстных процессоров
заключается в создании нескольких процессоров и в передачи им
RequestContext. Перепишем вышеприведённые
примеры с использованием контекстных процессоров:
from django.template import loader, RequestContext
def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}
def view_1(request):
# ...
t = loader.get_template('template1.html')
c = RequestContext(request, {'message': 'I am view 1.'},
processors=[custom_proc])
return t.render(c)
def view_2(request):
# ...
t = loader.get_template('template2.html')
c = RequestContext(request, {'message': 'I am the second view.'},
processors=[custom_proc])
return t.render(c)
def view_3(request):
# ...
t = loader.get_template('template3.html')
c = RequestContext(request, {'message': 'I am the third view.'},
processors=[custom_proc])
return t.render(c)
def view_4(request):
# ...
t = loader.get_template('template4.html')
c = RequestContext(request, {'message': 'I am the fourth view.'},
processors=[custom_proc])
return t.render(c)
Разберём этот код:
Сначала мы определили функцию
custom_proc. Это контекстный процессор, он принимает объектHttpRequestи возвращает словарь переменных для его последующего использования в контексте шаблона. Вот и всё что он делает.Мы изменили четыре функции представления так, чтобы они использовали
RequestContextвместоContext. Есть два различия в методике построения контекста. Первое,RequestContextтребует, чтобы первым аргументом былHttpRequest, который передаётся в функцию представления первым аргументом (request). Второе,RequestContextпринимает необязательный аргумент processors, который может быть списком или кортежем с функциями контекстного процессора, которые надо будет использовать. В нашем случае мы передалиcustom_proc— наш процессор, который мы определили ранее.Теперь каждое представление не нуждается больше во включении переменных
app,userиip_addressв её контекстную конструкцию, потому что они предоставляются функциейcustom_proc.Каждое представление всё ещё обладает возможностью введения любых своих шаблонных переменных, которые могут потребоваться. В данном примере шаблонная переменная
messageбыла передана в каждое представление.
В главе «Шаблоны» мы описали
сокращение render_to_response(), которое
позволяет вам не вызывать loader.get_template(),
затем создавать Context, а затем вызывать метод
render() для шаблона. Для того, чтобы
продемонстрировать низкоуровневую работу контекстных
процессоров, вышеприведённые примеры не используют сокращение
render_to_response(). Но это возможно и
предпочтительно. Сделаем это с помощью аргумента
context_instance:
from django.shortcuts import render_to_response
from django.template import RequestContext
def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}
def view_1(request):
# ...
return render_to_response('template1.html',
{'message': 'I am view 1.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_3(request):
# ...
return render_to_response('template3.html',
{'message': 'I am the third view.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_4(request):
# ...
return render_to_response('template4.html',
{'message': 'I am the fourth view.'},
context_instance=RequestContext(request, processors=[custom_proc]))
Здесь мы привели в порядок код обработки шаблона в каждой функции представления.
This is an improvement, but, evaluating the conciseness of this code, we have to admit we're now almost overdosing on the other end of the spectrum. FIXME. Мы убрали избыточность в данных (переменные нашего шаблона) за счёт добавления избыточности в код (в вызов processors). Использование контекстных процессоров не избавляет вас от необходимости набирать много строк кода.
По этим причинам Django предоставляет поддержку для
глобальных контекстных
процессоров. Параметр
TEMPLATE_CONTEXT_PROCESSORS[14] определяет то, какой процессор
должен всегда применяться к
RequestContext. Он исключает
необходимость указания processors при каждом
использовании RequestContext.
По умолчанию параметр
TEMPLATE_CONTEXT_PROCESSORS определён так:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
)
Этот параметр представляет собой кортеж вызываемых сущностей
FIXME???, которые используют тот же интерфейс, что и
вышеописанная функция custom_proc —
функции, принимающие объект запроса и возвращающие словарь
элементов, который затем включается в контекст. Следует
отметить, что значения параметра
TEMPLATE_CONTEXT_PROCESSORS указаны в виде
строк, которые определяют процессоры (они должны быть доступны
интерпретатору языка Python).
Процессоры применяются по порядку. Таким образом, если один процессор добавляет переменную в контекст, а затем второй процессор добавляет в контекст переменную с таким же именем, то второе значение перезапишет первое.
Django предоставляет ряд простых контекстных процессоров, включая активные по умолчанию:
Если параметр TEMPLATE_CONTEXT_PROCESSORS
содержит этот процессор, то каждый объект
RequestContext будет содержать
следующие переменные:
user: Экземпляр класса django.contrib.auth.models.User, представляющий текущего авторизованного пользователя. Если пользователь не авторизован, то это будет экземпляр класса
AnonymousUser.messages: Список сообщений (в виде строк) для текущего авторизованного пользователя. С технической точки зрения, эта переменная вызывает request.user.get_and_delete_messages() для каждого запроса. Этот метод получает пользовательские сообщения и удаляет их из базы данных.
perms: Экземпляр класса django.core.context_processors.PermWrapper, который представляет собой права текущего авторизованного пользователя.
В главе «Сессии, пользователи и регистрация» предоставлена информацию о пользователях, их правах и сообщениях.
Этот процессор помещает отладочную информацию в слой
шаблона. Если параметр
TEMPLATE_CONTEXT_PROCESSORS содержит этот
процессор, то каждый экземпляр класса
RequestContext будет содержать
следующие переменные:
debug: Значение параметра
DEBUG(True или False). Вы можете использовать эту переменную в шаблоне для определения работы в режиме отладки.sql_queries: Список словарей вида {'sql': ..., 'time': ...} представляющих каждый SQL запрос, который был выполнен во время обработки запроса и затраченное на это время. Порядок запросов в списке соответствует реальному порядку их выполнения.
Поскольку отладочная информация не предназначена для других глаз, этот контекстный процессор добавляет переменные к контексту только при выполнении обоих условий:
Параметр
DEBUGустановлен в True.Запрос пришёл с IP адреса указанного в списке
INTERNAL_IPS.
Если этот процессор включен, то каждый экземпляр класса
RequestContext будет содержать
следующие переменные:
LANGUAGES: Значение параметра LANGUAGES файла конфигурации.
LANGUAGE_CODE: Будет содержать значение request.LANGUAGE_CODE, если оно существует. В противном случае — значение параметра LANGUAGE_CODE файла конфигурации.
В приложении «Параметры конфигурации» об этих двух параметрах написано подробнее.
Если этот процессор включен, то каждый экземпляр класса
RequestContext будет содержать
переменную request, которая будет указывать на
текущий экземпляр класса
HttpRequest. Следует отметить, что этот
процессор не включен по умолчанию, вам потребуется
активировать его самостоятельно.
Вот несколько советов:
Каждый контекстный процессор должен отвечать за небольшую часть возможной функциональности. Очень просто использовать множество процессоров, таким образом вы можете разделять функциональность на логические части для повторного использования в будущем.
Следует помнить, что любой контекстный процессор, указанный в
TEMPLATE_CONTEXT_PROCESSORS, будет доступен в любом шаблоне, подчинённом данному файлу конфигурации. Таким образом, выбирайте имена переменных так, чтобы они не конфликтовали с именами переменных в ваших шаблонах. Так как имена переменных чувствительны к регистру, неплохо будет использовать прописные (т.е., большие) буквы для переменных, которые предоставляет процессор.Безразлично, где на файловой системе располагается контекстные процессоры, пока они находятся в пути интерпретатора. Учитывая это, удобно хранить их в файле
context_processors.pyвнутри вашего приложения или проекта.
| Пред. | Уровень выше | След. |
| Глава 10. Расширения для шаблонной системы | Начало | Загрузка шаблонов |
4 comments | Make a comment
Для django 1.4:
django.core.context_processors.auth переехал по адресу django.contrib.auth.context_processors.auth +
Сразу рекоммендую дописать процессор django.core.context_processor.static, чтобы потом не ломать голову со STATIC_URL
Кстати, в mysite/settings.py не было по умолчанию переменной TEMPLATE_CONTEXT_PROCESSORS = (...), пришлось добавить вручную. джанга 1.4, не знаю с чем это может быть связано даже, все таки php фрейм Yii в этом плане получше продуман. Там если генериться модуль или приложение, то уже все включено, а в джанге приходится с бубном вокруг гугля прыгать и выспрашивать у него - почему это не работает, почему то...))))))
answer to xnikolasx
Кстати, в mysite/settings.py не было по умолчанию переменной TEMPLATE_CONTEXT_PROCESSORS = (...), пришлось добавить вручную. джанга 1.4, не знаю с чем это может быть связано даже, все таки php фрейм Yii в этом плане получше продуман. Там если генериться модуль или приложение, то уже все включено, а в джанге приходится с бубном вокруг гугля прыгать и выспрашивать у него - почему это не работает, почему то...))))))
в 1.5.1 тоже по умолчанию нету
Вы сразу в код Django смотрите, бубен сохраннее будет.