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

Процессоры RequestContext и Context

Для обработки шаблона вам необходим контекст. Обычно это экземпляр 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 предоставляет ряд простых контекстных процессоров, включая активные по умолчанию:

Процессор django.core.context_processors.auth

Если параметр TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, то каждый объект RequestContext будет содержать следующие переменные:

  • user: Экземпляр класса django.contrib.auth.models.User, представляющий текущего авторизованного пользователя. Если пользователь не авторизован, то это будет экземпляр класса AnonymousUser.

  • messages: Список сообщений (в виде строк) для текущего авторизованного пользователя. С технической точки зрения, эта переменная вызывает request.user.get_and_delete_messages() для каждого запроса. Этот метод получает пользовательские сообщения и удаляет их из базы данных.

  • perms: Экземпляр класса django.core.context_processors.PermWrapper, который представляет собой права текущего авторизованного пользователя.

В главе «Сессии, пользователи и регистрация» предоставлена информацию о пользователях, их правах и сообщениях.

django.core.context_processors.debug

Этот процессор помещает отладочную информацию в слой шаблона. Если параметр TEMPLATE_CONTEXT_PROCESSORS содержит этот процессор, то каждый экземпляр класса RequestContext будет содержать следующие переменные:

  • debug: Значение параметра DEBUG (True или False). Вы можете использовать эту переменную в шаблоне для определения работы в режиме отладки.

  • sql_queries: Список словарей вида {'sql': ..., 'time': ...} представляющих каждый SQL запрос, который был выполнен во время обработки запроса и затраченное на это время. Порядок запросов в списке соответствует реальному порядку их выполнения.

Поскольку отладочная информация не предназначена для других глаз, этот контекстный процессор добавляет переменные к контексту только при выполнении обоих условий:

  • Параметр DEBUG установлен в True.

  • Запрос пришёл с IP адреса указанного в списке INTERNAL_IPS.

django.core.context_processors.i18n

Если этот процессор включен, то каждый экземпляр класса RequestContext будет содержать следующие переменные:

  • LANGUAGES: Значение параметра LANGUAGES файла конфигурации.

  • LANGUAGE_CODE: Будет содержать значение request.LANGUAGE_CODE, если оно существует. В противном случае — значение параметра LANGUAGE_CODE файла конфигурации.

В приложении «Параметры конфигурации» об этих двух параметрах написано подробнее.

django.core.context_processors.request

Если этот процессор включен, то каждый экземпляр класса RequestContext будет содержать переменную request, которая будет указывать на текущий экземпляр класса HttpRequest. Следует отметить, что этот процессор не включен по умолчанию, вам потребуется активировать его самостоятельно.

Как написать свой процессор?

Вот несколько советов:

  • Каждый контекстный процессор должен отвечать за небольшую часть возможной функциональности. Очень просто использовать множество процессоров, таким образом вы можете разделять функциональность на логические части для повторного использования в будущем.

  • Следует помнить, что любой контекстный процессор, указанный в TEMPLATE_CONTEXT_PROCESSORS, будет доступен в любом шаблоне, подчинённом данному файлу конфигурации. Таким образом, выбирайте имена переменных так, чтобы они не конфликтовали с именами переменных в ваших шаблонах. Так как имена переменных чувствительны к регистру, неплохо будет использовать прописные (т.е., большие) буквы для переменных, которые предоставляет процессор.

  • Безразлично, где на файловой системе располагается контекстные процессоры, пока они находятся в пути интерпретатора. Учитывая это, удобно хранить их в файле context_processors.py внутри вашего приложения или проекта.



[14] См. файл settings.py или глобальный файл конфигурации.


Увидели ошибку?
Выделите её мышкой и нажмите
Ctrl-Enter
Обработано:
1049 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