Наверно в каждом проекте есть система навигации — пользователи кликают по ссылкам, менюшкам и нам(разработчикам\дизайнерам\верстальщикам) надо как-то «подсвечивать» страницу\ссылку на которой сейчас находится пользователь.
Предоставляю не тривиальное решение очень тривиальной задачи при разработки навигации в Django проектах.
Для не терпеливых можно сразу взглянуть на проект на github.
В каждой вьюхе в контексте передаем некую переменную, пусть будет «location» и потом беспощадно хардкодим:
Получается — к каждой ссылки уникальное значение «location», что порождает очень много лишнего кода, когда ссылок\вьюх становится много практически не возможно запомнить какой «location» к какой ссылке, а так же верстальщик может быть крайне не доволен необходимостью вникать в логику питоновских вьюх и какое значение от куда попадает в контекст.
Можно передавать «location» такой же как именная ссылка данной вьюхи и навигация станет слегка наглядней.
собственно фильтр:
дальше в шаблоне:
Передавать переменные с вьюх уже не нужно, можно заменить сравнение на .startswith() или вовсе на регулярки и добавить поддержу меню, например светить ссылку на "/menu/" когда пользователь находится на странице "/menu/submenu/". Но рутина никуда не делась…
Рутинные действия напрочь отсутствуют, а именно:
немного магии…
Установка как и у всех питоновских батареек:
Все нюансы описаны тут.
Теперь, немного о том как всё это работает — из переданного html с помощью lxml строится дерево, в нем идет поиск HTML элементов которые надо подсветить(по умолчанию «li»), потом в этом тэге берутся все ссылки и их параметр «href» сравнивается с «request.get_full_path()».
Реализованные фичи:
Поменьше всем рутинных задач при разработке!
Предоставляю не тривиальное решение очень тривиальной задачи при разработки навигации в 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()».
Реализованные фичи:
- Выбор HTML элемента в котором искать ссылки
- Выбор CSS стиля который будет добавлен
- Поддержка меню
- Кэширование, во избежание излишних манипуляций с lxml
- Поддержка Jinja2 шаблонов
Поменьше всем рутинных задач при разработке!
