Django: выяснить, какой пункт в меню был выбран - PullRequest
4 голосов
/ 15 сентября 2009

Я уверен, что раньше видел этот вопрос о переполнении стека, но я не смог найти его своей жизнью, поэтому ничего не происходит.

У меня есть обычное меню Django, которое использует тег {% url %} и статические имена для пунктов меню. Теперь я хочу иметь другой стиль для пункта меню, который был выбран. Но меню отображается в базовом шаблоне, так как мне определить, какой это элемент меню?

Ответы [ 4 ]

6 голосов
/ 15 сентября 2009

Конечно, вы могли бы сделать это с помощью некрасивого шаблонного кода, но лучшим, более глобально известным способом является использование селектора CSS. Это позволяет CSS делать всю работу автоматически за вас.

Вот как это работает:

Вы просто помещаете идентификатор в свое тело в зависимости от того, на какой странице вы находитесь. Затем в CSS вы делаете что-то вроде этого:

#section-aboutme #nav-aboutme,
#section-contact #nav-contact
/* ... put one of these per body/menu item ... */
{
    font-color: red;
}

Вы добавляете идентификаторы nav-aboutme и nav-contact в каждый из пунктов вашего меню.

Стиль будет автоматически выбираться с помощью CSS в зависимости от того, какой идентификатор тела они внутри.

2 голосов
/ 15 марта 2011

Как насчет пользовательского тега, который вы используете для создания элемента навигации?

Ниже приводится имя URL, для которого должен быть создан элемент навигации, и текст, который он должен отображать. Он генерирует тег li с классом «selected», если путь указанного URL-адреса совпадает с текущим URL-адресом (в вашем TEMPLATE_CONTEXT_PROCESSORS требуется 'django.core.context_processors.request'). Внутри li он генерирует тег с путем URL, указанным url_name. Содержит содержимое, указанное contents.

Очевидно, что это может быть изменено для создания другой разметки для элемента навигации, как требуется.

Остальное можно сделать с помощью CSS.

Преимущества:

  • Простота в использовании

  • Маленький код требуется

  • DRY

  • Можно сделать более гибким

Недостатки:

  • Требуется 'django.core.context_processors.request'

  • Требуется указание URL, например, urlpatterns = patterns('django.views.generic.simple', ... (r'^$', 'direct_to_template', {'template': 'index.html'}, 'index'), ... ). Это потенциально может быть сделано по-другому (например, передать в URL).

  • Не справляется со страницами, не полностью равными указанному, и поэтому не будет применять выбранный класс к li, если он находится на странице ниже в иерархии URL. Например, если я нахожусь на / products /, он выделит пункт навигации, указывающий на / products /. Если я нахожусь на / products / myProduct /, он не будет выделять ссылку / products /. Это можно закодировать, но это заставит людей использовать разумные ссылки. Например, измените присвоение additionalAttrs на additionalAttrs = ' class=selected' if (context['request'].path.startswith(path) and path != '/') or (context['request'].path == path) else ''.

Код:

from django import template
from django.core.urlresolvers import reverse

register = template.Library()

class NavNode(template.Node):
    def __init__(self, url_name, contents):
        self.url_name = url_name
        self.contents = contents

    def render(self, context):
        path = reverse(self.url_name)
        additionalAttrs = ' class=selected' if path == context['request'].path else ''
        return '<li'+additionalAttrs+'><a href="'+path+'">'+self.contents+'</a></li>'

@register.tag
def nav_link(parser, token):
    bits = token.split_contents()
    if len(bits) == 3:
        contents = bits.pop()
        url_name = bits.pop()
    else:
        raise template.TemplateSyntaxError, "%r tag requires a single argument" % bits[0]

    if contents[0] == contents[-1] and contents[0] in ('"', "'"):
        contents = contents[1:-1]

    return NavNode(url_name, contents)                
2 голосов
/ 16 сентября 2009

Обычно я делаю это так, как предложил Брайан, но чтобы приспособиться к шаблону, который мне дал дизайнер, который использовал более распространенный метод class="selected", я написал {% nav%} шаблон тега .

Ваш HTML-шаблон навигации будет выглядеть примерно так:

{% block nav %}
<ul class="nav">
    <li{% if nav.home %} class="selected"{% endif %}><a href="/">Home</a></li>
    <li{% if nav.about %} class="selected"{% endif %}><a href="/about/">About</a></li>
</ul>
{% endblock %}

Чтобы установить навигацию в дочернем шаблоне, выполните:

{% include "base.html" %}
{% load nav %}

{% block nav %}
{% nav "about" %}
{{ block.super }}
{% endblock %}
1 голос
/ 16 сентября 2009

Вы можете передать request.path вашему шаблону

from django.shortcuts import render_to_response
from django.template import RequestContext
return render_to_response('templ.html', {'page':request.path}, context_instance=RequestContext(request))

затем используйте уродливый тег if для добавления класса CSS в ваш пункт меню

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...