Джанго: Есть ли лучший способ выделить ссылку на текущую страницу?

У меня есть шаблон base.html, который содержит список ссылок.

Пример:

   <div id="sidebar1">
        <ul>
        <li><a href="/" title="">Index</a></li>
        <li><a href="/stuff/" title="" class="current">Stuff</a></li>
        <li><a href="/about/" title="">About Me</a></li>
        <li><a href="/contact/" title="">Contact Me</a></li>
    </div>

Затем в моем views.py есть определение для каждого из index.html, stuff.html, about.html и contact.html. Каждый из этих шаблонов просто происходит от шаблона base.html и устанавливает свои собственные соответствующие заголовки и содержимое.

Мой вопрос о вышеупомянутом / материале у меня есть класс = "текущий".

Я бы хотел, чтобы текущая страница, на которой я нахожусь, имела атрибут class.

Я мог бы установить разные переменные в каждом представлении, например current_page="about", а затем сделать сравнение в шаблоне с {% ifequal %} в каждом элементе класса каждой ссылки, но это похоже на дублирование работы (из-за дополнительной переменной представления).

Есть ли способ лучше? Может быть, если есть способ получить имя функции представления, из которой шаблон был заполнен автоматически, мне не нужно было бы устанавливать дополнительную переменную? Кроме того, это похоже на много ифеков.

4 ответа

Решение

Вот элегантный способ сделать это, который я скопировал откуда-то, и мне только хотелось бы вспомнить, где, чтобы я мог отдать им должное. 8-)

Я назначаю id для каждой из моих страниц (или всех страниц в разделе), как это:

In index.html:    <body id='section-intro'>...
In faq.html:      <body id='section-faq'>...
In download.html: <body id='section-download'>...

А потом id для соответствующих ссылок:

<li id='nav-intro'><a href="./">Introduction</a></li>
<li id='nav-faq'><a href="./faq.html">FAQ</a></li>
<li id='nav-download'><a href="./download.html">Download</a></li>

И в CSS я установил правило так:

#section-intro #nav-intro,
#section-faq #nav-faq,
#section-download #nav-download {
    font-weight: bold;
    /* And whatever other styles the current link should have. */
}

Так что это работает в основном декларативным способом управления стилем ссылки, к которой принадлежит текущая страница. Вы можете увидеть это в действии здесь: http://entrian.com/source-search/

Это очень чистая и простая система после ее настройки, потому что:

  • Вам не нужно возиться с разметкой шаблона в ваших ссылках
  • Вы не в конечном итоге использовать большой уродливый switch заявления или if / else / else заявления
  • Добавление страниц в раздел Just Works [TM]
  • Изменение только того, как все выглядит, означает изменение CSS, а не разметки.

Я не использую Django, но эта система работает где угодно. В вашем случае, когда вы "устанавливаете свои собственные соответствующие заголовки и содержание", вам также необходимо установить body idи никакой другой разметки Django не требуется.

Эта идея легко распространяется и на другие ситуации, например. "Мне нужна ссылка для скачивания на боковой панели на каждой странице, кроме самих страниц загрузки". Вы можете сделать это в CSS следующим образом:

#section-download #sidebar #download-link {
    display: none;
}

вместо того, чтобы помещать условную разметку шаблона в боковую панель HTML.

Я не использовал Django, но я имел дело с той же проблемой в Kohana (PHP) и Rails.

Что я делаю в Кохане:

<li><a href="/admin/dashboard" <?= (get_class($this) == 'Dashboard_Controller') ? "class=\"active\"" : NULL ?>>Dashboard</a></li>
<li><a href="/admin/campaigns" <?= (get_class($this) == 'Campaigns_Controller') ? "class=\"active\"" : NULL ?>>Campaigns</a></li>
<li><a href="/admin/lists" <?= (get_class($this) == 'Lists_Controller') ? "class=\"active\"" : NULL ?>>Lists</a></li>

Что я делаю в Rails:

<li><a href="/main" <%= 'class="active"' if (controller.controller_name == 'main') %>>Overview</a></li>
<li><a href="/notifications" <%= 'class="active"' if (controller.controller_name == 'notifications') %>>Notifications</a></li>
<li><a href="/reports" <%= 'class="active"' if (controller.controller_name == 'reports') %>>Reports</a></li>

Если вы добавите request контекстный процессор, это довольно просто:

settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth'  # admin app wants this too
)

Теперь у вас есть доступ к HttpRequest, который содержит путь запроса. Выделение текущей страницы - это простой вопрос проверки, соответствует ли путь месту назначения ссылки, т. Е. Вы уже там:

<li><a class="{% if request.path == '/' %}current{% endif %}" href="/">Index</a></li>
<li><a class="{% if request.path == '/stuff/' %}current{% endif %}" href="/stuff/">Stuff</a></li>
<li><a class="{% if request.path == '/about/' %}current{% endif %}" href="/about/">About Me</a></li>
<li><a class="{% if request.path == '/contact/' %}current{% endif %}" href="/contact/">Contact Me</a></li>

Я вижу только несколько способов сделать это, избегая повторяющихся ифекалов:

  1. Javascript. Что-то вроде (jQuery):

    var parts = window.location.pathname.split('/');
    var page = parts[parts.length-1];
    $('#sidebar1 a[href*=' + page + ']').addClass('current');
    
  2. Измените ваши представления так, чтобы они содержали список страниц со связанными с ними заголовками и URL-адресами, и создайте в шаблоне цикл {% for %}, который пройдет по этому списку и добавит один {% ifequal %}.

Вариант 2 - любимый, где я стою. Если логика для всех ваших страниц одинакова и отличаются только шаблоны, вы можете рассмотреть возможность использования модели FlatPages для каждой из ваших страниц. Если логика отличается, и вам нужны разные модели, вы можете рассмотреть возможность использования какого-либо приложения для меню. Бесстыдная вилка: у меня есть собственное приложение для меню

Другие вопросы по тегам