Шаблонные контекстные процессоры

Курс по Django: https://stepik.org/a/183363

Архив проекта: 61_sitewomen.zip

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

Мы помним, что приложения в проекте Django следует делать максимально независимым от друг от друга. Поэтому отображение меню лучше сделать непосредственно в базовом шаблоне, передавая ему объект-меню, например, в виде списка. Этот функционал можно реализовать несколькими способами. Используя только текущие знания, первое, что приходит на ум, это воспользоваться простым пользовательским тегом. Давайте, для примера, это сделаем. Перейдем в файл women_tags.py и определим simple тег для проброса списка меню в шаблон:

@register.simple_tag
def get_menu():
    return menu

А в шаблоне base.html воспользуемся им:

{% get_menu as menu %}

Все, теперь отдельно меню передавать в шаблон не нужно, поэтому в файле women/utils.py уберем его из класса DataMixin. (Обновляем страницу, видим отображение главного меню.)

Контекстные процессоры

Однако когда предполагается во все шаблоны проекта передавать какую-либо независимую информацию, как, например, главное меню, то можно воспользоваться еще одним механизмом – шаблонными контекстными процессорами.  Что это такое? Если открыть файл settings.py, то в коллекции TEMPLATES в списке context_processors видим перечисление существующих контекстов. Например, context_processors.request формирует переменную request во всех наших шаблонах, а auth.context_processors.auth обеспечивает переменной user. И нам ничто не мешает создать свой собственный шаблонный контекстный процессор для передачи списка пунктов главного меню.

В приложении users создадим еще один вспомогательный файл с именем context_processors.py и в нем создадим свой контекст для шаблона следующим образом:

from women.utils import menu
 
 
def get_women_context(request):
    return {'mainmenu': menu}

Как видите, это невероятно просто! Осталось его прописать в списке других контекстных процессоров (в файле settings.py):

       
    'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'users.context_processors.get_women_context'
            ],

Все, теперь во все наши шаблоны будет автоматически передаваться переменная mainmenu со списком главного меню. Давайте ее используем в шаблоне base.html вместо переменной menu. А тег, который пробрасывал переменную menu в шаблон можно убрать.

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

Доработка панели главного меню

В заключение занятия сделаем еще одно изменение. Удалим из списка menu последнюю строчку для login. Мы пропишем ее отдельно в шаблоне. Откроем файл base.html и меню будем формировать следующим образом:

{% block mainmenu %}
                   <div class="header">
                            <ul id="mainmenu" class="mainmenu">
                            <li class="logo"><a href="{% url 'home' %}"><div class="logo"></div></a></li>
{% for m in mainmenu %}
                            <li><a href="{% url m.url_name %}">{{m.title}}</a></li>
{% endfor %}
                            <li class="last"><a href="{% url 'users:login' %}">Войти</a></li>
                            </ul>
                            <div class="clear"></div>
                   </div>
{% endblock mainmenu %}

Обратите внимание, как указано имя маршрута для login. Вначале идет пространство имен users, а через двоеточие – имя login. Напомню, что это пространство имен мы с вами определили в файле urls.py пакета конфигурации, когда подключали через функцию include() файл users/urls.py. Благодаря этому мы на уровне шаблонов можем четко разграничивать имена маршрутов для приложения users и других программных компонент. В частности, если прописать просто имя login, то получим другой маршрут с этим именем, прописанный в файле women/urls.py.

И последнее, что мы сделаем – это отобразим в главном меню имя пользователя, если он авторизован, либо пункт «Войти» и «Регистрация», если не авторизован. Для этого, опять же в главном шаблоне base.html пропишем следующую проверку:

{% if user.is_authenticated %}
<li class="last"> {{user.username}} | <a href="{% url 'users:logout' %}">Выйти</a></li>
{% else %}
<li class="last"><a href="{% url 'users:login' %}">Войти</a> | <a href="#">Регистрация</a></li>
{% endif %}

Здесь используется объект user, связанный с текущим пользователем, и уже у этого объекта проверяем свойство is_authenticated. Если оно принимает значение True, значит, пользователь авторизован, иначе – не авторизован. Для авторизованных пользователей отображается ссылка «Выйти» с именем маршрута logout. А для неавторизованных ссылки «Войти» и «Регистрация».

Давайте нажмем на ссылку «Войти» и в форме авторизации введем данные суперпользователя. Видим, на панели отобразилось имя пользователя и пункт «Выйти». Нажимаем на выход, попадаем снова на страницу авторизации.

Курс по Django: https://stepik.org/a/183363

Видео по теме