Django: есть ли лучший способ выделить ссылку на текущую страницу? - PullRequest
7 голосов
/ 21 июня 2009

У меня есть шаблон 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 ]

16 голосов
/ 21 июня 2009

Вот элегантный способ сделать это, который я скопировал откуда-то, и я только хотел бы вспомнить, где, чтобы я мог отдать им должное. 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.

2 голосов
/ 21 июня 2009

Не использовал 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>
1 голос
/ 30 октября 2013

Если вы добавите процессор контекста 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 голос
/ 21 июня 2009

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

  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 для каждой из ваших страниц. Если логика отличается и вам нужны разные модели, вы можете рассмотреть возможность использования какого-либо приложения для меню. Бесстыдная штепсельная вилка: у меня есть приложение для работы с меню моего собственного

...