Наверно в каждом проекте есть система навигации — пользователи кликают по ссылкам, менюшкам и нам(разработчикам\дизайнерам\верстальщикам) надо как-то «подсвечивать» страницу\ссылку на которой сейчас находится пользователь.
Предоставляю не тривиальное решение очень тривиальной задачи при разработки навигации в 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 шаблонов
Поменьше всем рутинных задач при разработке!