Django - выделить навигацию на основе текущей страницы?
Я строю веб-приложение, которое имеет несколько основных разделов. Каждый раздел имеет несколько подразделов. у меня есть main_nav.html
файл, который содержит навигацию для основного раздела. Это добавлено к основанным HTML
файл с {% include ... %}
команда в base.html
шаблон. Кроме того, у меня есть несколько навигационных файлов подразделов, каждый из которых добавляется на любую страницу с одинаковыми {% include ... %}
команда.
Все навигационные панели очень простые, просто текст с <a href...>
теги.
Я хочу выделить ссылку на текущий основной раздел и текущий подраздел. Поскольку это веб-приложение довольно большое, я надеялся как-то сделать это, не добавляя информацию, относящуюся к конкретной странице. Кроме того, я хочу, чтобы он просто "работал", поскольку веб-приложение расширяется и включает больше разделов и подразделов. Например, можно ли это сделать, посмотрев на действующий URL-адрес? Я надеялся поместить это в сами файлы nav и не загружать какую-либо переменную или что-либо еще в каждом представлении django.
Так, например, навигация выглядит так:
(main ->) [Systems][Invoices][Work Orders][Admin]
(system sub-nav ->) [Owner][Billing][Contacts]
Так что если я в Billing
раздел Systems
Хочу ссылку Systems
жирным шрифтом и ссылка Billing
быть смелым (или какой-то другой простой момент)
Или же:
(main ->) [Systems][Invoices][Work Orders][Admin]
(Work-Orders sub-nav ->) [Create New][Outstanding]
Если я в Outstanding
раздел Work Orders
, ссылка Work Orders
и ссылка Outstanding
должен быть выделен.
Есть идеи?
8 ответов
Предполагая, что вы используете render_to_response
с RequestContext
или используйте render
Представления Django 1.3, основанные на методах или классах, будут содержать объект запроса в вашем шаблоне. Отсюда просто получить доступ к текущему пути и сравнить его с ожидаемыми значениями:
<a href="/some/path/to/be/highlighted/"{% if request.path == '/some/path/to/be/highlighted/' %} class="active"{% endif %}>Some Link</a>
В Django 1.3 мне нравится сохранять избыточность и использовать as
оператор для поиска URL:
{% url 'some_urlpattern_name' as url %}
<a href="{{ url }}"{% if request.path == url %} class="active"{% endif %}>Some Link</a>
Повторите по мере необходимости для каждой ссылки.
Развивая принятый ответ Криса, вы можете использовать тот факт, что язык шаблонов Django поддерживает in
для частичного соответствия. Так, например, если у вас есть такие URL, как
/people/directory
/people/profiles/joe
/people/profiles/edit
и вы хотите, чтобы основной навигационный элемент "Люди" выделен для всех этих случаев, используйте что-то вроде:
{% if "/people/" in request.path %}class="active"{% endif %}
Просто подумал, что я добавлю свой подход для других, чтобы рассмотреть, если они найдут это в Google.
В моих шаблонах у меня есть что-то вроде этого:
{% block pagename %}homepage{% endblock %}
Затем в моем основном шаблоне, что-то вроде этого (чтобы имя страницы из шаблона наследования было доступно для отображаемой страницы):
<span id="_pageName" style="display:none">{% block pagename %}{% endblock %}</span>
Мои ссылки выглядят так:
<li data-link-name="homepage"><a href="{% url "pages:home" %}">Home</a></li>
Все, что вам нужно, это немного javascript для применения вашего CSS-класса к правильной ссылке при загрузке страницы. Мой выглядит примерно так:
$(function() {
var pageName = document.getElementById('_pageName');
if (pageName != null) { pageName = pageName.innerHTML; }
else { pageName = ''; }
if (pageName.length > 0) {
$("li[data-link-name='" + pageName + "']").addClass('active');
}
});
Очень просто, дает вам контроль над тем, какую ссылку выделить, добавив крошечный блок в ваши шаблоны.
В другом подобном вопросе я видел ответы jpwatts', 110j' s, nivhab& Marcus Whybrow, но, похоже, им всем не хватает чего-то: как насчет корневого пути? Почему это всегда активно?
Так что я сделал другой, более простой способ, который заставляет "контроллер" решать сам, и я думаю, что он решает большинство больших проблем.
Вот мой пользовательский тег:
## myapp_tags.py
@register.simple_tag
def nav_css_class(page_class):
if not page_class:
return ""
else:
return page_class
Затем "контроллер" объявляет необходимые классы CSS (на самом деле, самое важное, он объявляет о своем присутствии в шаблоне)
## views.py
def ping(request):
context={}
context["nav_ping"] = "active"
return render(request, 'myapp/ping.html',context)
И, наконец, я отображаю это в моей панели навигации:
<!-- sidebar.html -->
{% load myapp_tags %}
...
<a class="{% nav_css_class nav_home %}" href="{% url 'index' %}">
Accueil
</a>
<a class="{% nav_css_class nav_candidats %}" href="{% url 'candidats' %}">
Candidats
</a>
<a class="{% nav_css_class nav_ping %}" href="{% url 'ping' %}">
Ping
</a>
<a class="{% nav_css_class nav_stat %}" href="{% url 'statistiques' %}">
Statistiques
</a>
...
Так что каждая страница имеет свою nav_css_class
значение для установки, и если оно установлено, шаблон становится активным: нет необходимости request
в контексте шаблона не нужно разбирать URL-адреса и больше не возникает проблем с много-URL-страницами или корневой страницей.
Даже проще, чем использовать
as
оператор (текущий верхний ответ) помещает следующее
if
вокруг любых изменений HTML или CSS, которые вы хотите сделать, чтобы показать страницу как активную:
{% if request.resolver_match.url_name == 'your_active_url_pattern_name' %}
Если вы хотите обрабатывать сложные URL-адреса с помощью Unicode, не забудьте использовать
iriencode
( https://docs.djangoproject.com/en/dev/ref/templates/builtins/#iriencode)
{% url 'your_view_name_defined_in_urls.py' possible_attribute as url %}
<a class="{% if request.path|iriencode == url %}active{% endif %}" href="{{ url }}">
Your label
</a>
{% if "/people/" в request.path %}class="active"{% endif %}
Это самое или лучшее решение, вот как реализовать
{% if "/customer_account" in request.path %}
<a href="/customer_account" class="item active">
<div class="col">
<ion-icon name="person-outline"></ion-icon>
<strong class="cusb">My Account</strong>
</div>
</a>
{% else %}
<a href="/customer_account" class="item">
<div class="col">
<ion-icon name="person-outline"></ion-icon>
<strong class="cusb">My Account</strong>
</div>
</a>
{% endif %}
В продолжение ответа fabspro, вот способ сделать это на основе URL страниц и с помощью vanilla js.
<div id="navbar">
<ul>
<li data-link-name="home">
<a href="{% url 'home' %}"><span>Home</span></a>
</li>
<li data-link-name="parent">
<a href="{% url 'myapp:index' %}"><span>Parent</span></a>
</li>
<li data-link-name="child1">
<a href="/myapp/child1/grandchild1"><span>Child 1</span></a>
</li>
</ul>
</div>
<script>
var path = location.pathname;
if (path == "/") {
pageName = "home";
} else if (path.startsWith("/myapp/child1")){
pageName = "child1";
} else if (path.startsWith("/myapp")) {
pageName = "parent";
}
document.querySelector("li[data-link-name='" + pageName + "']").classList += "active";
</script>
Здесь много гибкости. Например, Parent
ссылка выше будет выделена для всех URL-адресов, кроме /child1
, Child 1
ссылка приведет пользователя к /grandchild1
страница, но ссылка будет показана активной для всех grandchildren
в child1
, Любая логика может быть написана на самом деле.