Как стать автором
Обновить

Навигация в шаблонах Django

Время на прочтение2 мин
Количество просмотров19K
Наверно в каждом проекте есть система навигации — пользователи кликают по ссылкам, менюшкам и нам(разработчикам\дизайнерам\верстальщикам) надо как-то «подсвечивать» страницу\ссылку на которой сейчас находится пользователь.

Предоставляю не тривиальное решение очень тривиальной задачи при разработки навигации в Django проектах.

Для не терпеливых можно сразу взглянуть на проект на github.

Самое тривиальное решение


В каждой вьюхе в контексте передаем некую переменную, пусть будет «location» и потом беспощадно хардкодим:

<ul>
  <li {% if location=='random_page' %} class="active" {% endif %}>
    <a href="{% url 'random_page' %}">
      {% trans 'random page' %}
    </a>
  </li>
</ul>

Получается — к каждой ссылки уникальное значение «location», что порождает очень много лишнего кода, когда ссылок\вьюх становится много практически не возможно запомнить какой «location» к какой ссылке, а так же верстальщик может быть крайне не доволен необходимостью вникать в логику питоновских вьюх и какое значение от куда попадает в контекст.

Можно передавать «location» такой же как именная ссылка данной вьюхи и навигация станет слегка наглядней.

Реализация через простой «template filter»


собственно фильтр:

from django import template


register = template.Library()


def active(url, request):
    if url == request.get_full_path():
        return True
    else:
        return False


register.filter('active', active)

дальше в шаблоне:

{% load active %}

<ul>
  {% url 'random_page' as random_page %}
  <li {% if random_page|active:request %} class="active" {% endif %}>
    <a href="{{ random_page }}">
      {% trans 'random page' %}
    </a>
  </li>
</ul>

Передавать переменные с вьюх уже не нужно, можно заменить сравнение на .startswith() или вовсе на регулярки и добавить поддержу меню, например светить ссылку на "/menu/" когда пользователь находится на странице "/menu/submenu/". Но рутина никуда не делась…

Мои велосипеды — django-activeurl


Рутинные действия напрочь отсутствуют, а именно:

{% load activeurl %}

{% activeurl %}
  <ul>
    <li>
      <a href="{% url 'random_page' %}">
        {% trans 'random page' %}
      </a>
    </li>
  </ul>
{% endactiveurl %}

немного магии…

<ul>
  <li class="active">
    <a href="/random_page/">
      random page
    </a>
  </li>
</ul>

Установка как и у всех питоновских батареек:

pip install django-activeurl

Все нюансы описаны тут.

Теперь, немного о том как всё это работает — из переданного html с помощью lxml строится дерево, в нем идет поиск HTML элементов которые надо подсветить(по умолчанию «li»), потом в этом тэге берутся все ссылки и их параметр «href» сравнивается с «request.get_full_path()».

Реализованные фичи:


Поменьше всем рутинных задач при разработке!
Теги:
Хабы:
Всего голосов 10: ↑6 и ↓4+2
Комментарии11

Публикации

Истории

Работа

Python разработчик
121 вакансия

Ближайшие события

15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань