Django - Выделить подсветку на основе текущей страницы?

Я создаю webapp, который имеет несколько основных разделов. Каждая секция имеет несколько подсекций. У меня есть файл main_nav.html, который содержит навигацию для основного раздела. Это добавляется в файл HTML с помощью команды {% include ... %} в шаблоне base.html. Кроме того, у меня есть несколько навигационных файлов sub-section, каждый из которых добавляется на любую страницу с той же командой {% include ... %}.

Все навигационные бары очень просты, просто текст с тегами <a href...>.

Я хочу выделить ссылку для текущего основного раздела и текущего подраздела. Поскольку этот webapp довольно большой, я надеялся каким-то образом сделать это, не добавляя информацию о странице. Кроме того, я хочу, чтобы он просто "работал" с расширением webapp, чтобы включить больше разделов и подразделов. Например, можно ли это сделать, посмотрев фактический URL-адрес? Я надеялся разместить это в самих файлах навигации и не должен загружать какую-либо переменную или что-то в каждом представлении django.

Итак, например, nav выглядит так:

(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 должны быть выделены.

Любые идеи?

Ответ 1

Предполагая, что вы используете 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>

Повторите, если необходимо, для каждой ссылки.

Ответ 2

Просто подумал, что я брошу свой подход, чтобы другие подумали, нашли ли они это в 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');
    }
});

Очень просто, дает вам контроль над тем, какую ссылку выделить, добавив крошечный блок в свои шаблоны.

Ответ 3

В другом подобном вопросе, я видел jpwatts ', 110j, 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-адресами или с корневым стр.

Ответ 4

Расширяя принятый ответ Криса, вы можете использовать тот факт, что язык шаблонов Django поддерживает in для частичного сопоставления. Например, если у вас есть URL-адреса, например

/people/directory
/people/profiles/joe
/people/profiles/edit

и вы хотите, чтобы основной элемент "Люди" был выделен для всех этих случаев, используйте что-то вроде:

{% if "/people/" in request.path %}class="active"{% endif %}

Ответ 5

Развернувшись на ответе fabspro, здесь можно сделать это на основе URL-адресов страниц и с помощью ванильных 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. Любая специальная логика может быть написана на самом деле.