장고 내비게이션


104

나는 django에서 나의 첫 번째 작은 webapp을 방금했고 그것을 좋아합니다. 이전 프로덕션 PHP 사이트를 django로 변환하는 작업을 시작하려고하며 템플릿의 일부로 탐색 모음이 있습니다.

PHP에서는 템플릿 코드에서 현재 URL과 비교하여 각 nav 옵션의 URL을 확인하고 정렬되면 CSS 클래스를 적용합니다. 끔찍하게 지저분합니다.

django에 더 좋은 것이 있거나 템플릿에서 코드를 처리하는 좋은 방법이 있습니까?

시작하려면 현재 URL을 가져 오는 방법은 무엇입니까?


이를 위해 github.com/orokusaki/django-active-menu 를 만들었습니다. 중첩 된 URL 구조를 지원하고 규칙에 대한 구성에 의존하므로 (그렇게 들리 겠지만) 원하는대로 사이트의 계층을 정의 할 수 있습니다. 당신은 단지 <a href="{% url "view:name" %}" {% active_class "view:name" %}>. 선택적으로 생성하는 데 사용할 수 있습니다 단지" active" (전달하여 값을 False기존 클래스의 속성에 추가 할 태그에 두 번째 인수로)하지만, 대부분의 탐색 링크에 대한 예는 내가 사용하는 것입니다.
orokusaki

이 질문은이 일에 관련이있을 것으로 보인다 stackoverflow.com/a/9801473/5739875
예브게니 Bobkin에게

이 그리드가 도움이 될 수 있습니다 : djangopackages.org/grids/g/navigation
guettli

답변:


74

템플릿 상속을 사용하여 탐색을 사용자 지정합니다. 예를 들면 :

base.html

<html>
    <head>...</head>
    <body>
        ...
        {% block nav %}
        <ul id="nav">
            <li>{% block nav-home %}<a href="{% url home %}">Home</a>{% endblock %}</li>
            <li>{% block nav-about %}<a href="{% url about %}">About</a>{% endblock %}</li>
            <li>{% block nav-contact %}<a href="{% url contact %}">Contact</a>{% endblock %}</li>
        </ul>
        {% endblock %}
        ...
    </body>
</html>

about.html

{% extends "base.html" %}

{% block nav-about %}<strong class="nav-active">About</strong>{% endblock %}

특히 유연성 측면에서이 아이디어를 많이 좋아하지만 덜 건조하게 절충해야합니다. 나는 이것을 사이트에서 사용하기 시작했습니다.
익명의 겁쟁이

22
동일한 하위 템플릿에서 여러 사이트 섹션을 처리하는 것이 드문 일이 아니기 때문에이 접근 방식에 열광하지 않습니다. 따라서 사용자 지정 변수를 뷰에 배치하고 템플릿의 조건을 지정하거나 하위 템플릿을 다시 정렬하여 모두 고유하게 만듭니다.이 모든 것이 현재 사이트 섹션을 감지하기위한 것입니다. 템플릿 태그 접근 방식은 결국 더 깔끔해집니다.
shacker 2010

몇 가지 다른 솔루션을 살펴본 결과 모두 약간의 해킹 인 것 같습니다. 이것은 적어도 구현 / 스크랩하기가 매우 간단하고 간단합니다.
mlissner 2011

나는 <ul id="nav">....</ul>다른 파일로 리팩토링했습니다 . tabs.html이라고합시다. 이제 base.html이 포함 된 {%block nav%}{%include "tabs.html"%}{%endblock%}다음 활성 탭의 강조 표시가 작동을 멈췄습니다 (위의 about.html에서). 내가 놓친 것이 있습니까?
None-da

@Maddy 당신은 내가 그것을 내 머리 속에 똑바로 유지하고 있는지 확실하지 않다는 충분한 간접적 인 지시를 받았지만 대답은 include태그가 작동 하는 방식과 관련이 있다고 생각 합니다. 하여 문서에 포함 된 참고 체크 아웃 : docs.djangoproject.com/en/dev/ref/templates/builtins/#include을 당신이 기본 템플릿을 무시하려고하는 시간으로, 귀하의 경우에 about.html, 나는 당신이했다고 생각 처리 대기중인 Django 템플릿 블록이 아니라 이미 렌더링 된 HTML 블록이 있습니다.
jpwatts 2011 년

117

그렇게하려면 if가 필요하지 않습니다. 다음 코드를 살펴보세요.

tags.py

@register.simple_tag
def active(request, pattern):
    import re
    if re.search(pattern, request.path):
        return 'active'
    return ''

urls.py

urlpatterns += patterns('',
    (r'/$', view_home_method, 'home_url_name'),
    (r'/services/$', view_services_method, 'services_url_name'),
    (r'/contact/$', view_contact_method, 'contact_url_name'),
)

base.html

{% load tags %}

{% url 'home_url_name' as home %}
{% url 'services_url_name' as services %}
{% url 'contact_url_name' as contact %}

<div id="navigation">
    <a class="{% active request home %}" href="{{ home }}">Home</a>
    <a class="{% active request services %}" href="{{ services }}">Services</a>
    <a class="{% active request contact %}" href="{{ contact }}">Contact</a>
</div>

그게 다야. 구현 세부 사항은
gnuvince.wordpress.com
110j.wordpress.com을 참조하십시오.


2
href의 속성에 django 템플릿 대괄호 {{,}}가 없습니다. 예를 들어 <a class="{% active request home %}" href="home"> 홈 </a>은 <a class = "{% active request home %}"href = "{{home}이어야합니다. } "> 홈 </a>은 tags.py 파일에도 몇 가지 포함이 필요합니다. 그렇지 않으면 훌륭한 솔루션입니다!
bsk

2
+1 이것은 응용 프로그램과 더 느슨하게 결합됩니다. 초보자로서 태그에 자체 앱이 필요하다는 것을 알았습니다.이를 글로벌 tags.py 파일에 덤프 할 수는 없습니다. 태그라는 새로운 앱을 만들었고 모든 것이 순조롭게 진행되었습니다. docs.djangoproject.com/en/dev/howto/custom-template-tags
Keyo

3
@Keyo, 프로젝트에 templatetags 디렉터리를 만들고 설치된 앱에 프로젝트를 추가합니다. 그것은 또한 트릭을 할 것입니다. 또는 말했듯이 프로젝트 내에서 기본 사이트를 앱으로 만듭니다.
Josh Smeaton 2011 년

5
추가하는 것을 잊지 마십시오 django.core.context_processors.request당신에 TEMPLATE_CONTEXT_PROCESSORSsettings.py
amigcamel

1
이는 중첩 될 수있는 상태, 예를 들어 mysite.com(홈으로) 및으로 유효하지 않습니다 mysite.com/blog. 경로가로 표시 /되고 /blog/(각각) 매번 전자에 대한 일치를 산출하기 때문입니다. /랜딩으로 사용하지 않으면 괜찮을 수 있습니다. 그렇지 않으면 그냥 사용합니다 return 'active' if pattern == request.path else ''(아직 문제를 보지 못했지만 이것을 사용하여 설정했습니다).
nerdwaller

33

나는 위의 110j의 청결 함이 마음에 들었 기 때문에 대부분을 가져 와서 내가 가진 세 가지 문제를 해결하기 위해 리팩토링했습니다.

  1. 정규식이 '홈'URL을 다른 모든 URL과 일치 시켰습니다.
  2. 하나의 탐색 탭에 매핑 된 여러 URL이 필요 했기 때문에 가변적 인 양의 매개 변수를 사용하는 더 복잡한 태그가 필요했습니다.
  3. 일부 URL 문제 수정

여기있어:

tags.py :

from django import template

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, patterns):
        self.patterns = patterns
    def render(self, context):
        path = context['request'].path
        for p in self.patterns:
            pValue = template.Variable(p).resolve(context)
            if path == pValue:
                return "active" # change this if needed for other bootstrap version (compatible with 3.2)
        return ""

urls.py :

urlpatterns += patterns('',
    url(r'/$', view_home_method, {}, name='home_url_name'),
    url(r'/services/$', view_services_method, {}, name='services_url_name'),
    url(r'/contact/$', view_contact_method, {}, name='contact_url_name'),
    url(r'/contact/$', view_contact2_method, {}, name='contact2_url_name'),
)

base.html :

{% load tags %}

{% url home_url_name as home %}
{% url services_url_name as services %}
{% url contact_url_name as contact %}
{% url contact2_url_name as contact2 %}

<div id="navigation">
    <a class="{% active request home %}" href="home">Home</a>
    <a class="{% active request services %}" href="services">Services</a>
    <a class="{% active request contact contact2 %}" href="contact">Contact</a>
</div>

아마 우리가 마커스 원에 대한 최선의 대답일지도 모르지만 "집"과 어떻게 작동합니까? 항상 활성화되어 있습니까? 루트 URL 호출 (www.toto.com/ 및 www.toto.com/index)에서만 활성화하는 방법은 무엇입니까? 두 답변 ...이 문제가되지 않는
DestyNova

20

저는 이 질문을 해결하기 위해 특별히 쓴 django-lineage 의 저자입니다 .

나는 내 프로젝트에서 (완벽하게 수용 가능한) jpwatts 방법을 사용하여 짜증이 나고 110j의 대답에서 영감을 얻었습니다. 리니지는 다음과 같습니다.

{% load lineage %}
<div id="navigation">
    <a class="{% ancestor '/home/' %}" href="/home/">Home</a>
    <a class="{% ancestor '/services/' %}" href="/services/">Services</a>
    <a class="{% ancestor '/contact/' %}" href="/contact/">Contact</a>
</div>

ancestor 인수가 현재 페이지 URL의 시작과 일치하면 단순히 "활성"으로 바뀝니다.

가변 인수 및 전체 {% url %}유형 역방향 해상도도 지원됩니다. 나는 몇 가지 구성 옵션을 뿌려서 약간 구체화하고 모든 사람이 사용할 수 있도록 패키지화했습니다.

관심이 있으시면 다음 사이트에서 자세히 읽어보십시오.

>> github.com/marcuswhybrow/django-lineage


1
템플릿에 하드 코딩 경로 :(
CpILL

10

Django 1.5 이후 :

모든 일반 클래스 기반 뷰 (또는 ContextMixin에서 상속 된 클래스 기반 뷰)에서 컨텍스트 사전에는 View 인스턴스를 가리키는 뷰 변수가 포함됩니다.

따라서 이러한 뷰를 사용 breadcrumbs하는 경우 클래스 수준 필드로 원하는 것을 추가하고 템플릿에서 사용할 수 있습니다.

보기 코드 예 :

class YourDetailView(DetailView):
     breadcrumbs = ['detail']
     (...)

템플릿에서 다음과 같이 사용할 수 있습니다.

<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>

상위 탐색 항목을 추가로 "강조 표시"하려면 breadcrumbs목록 을 확장해야 합니다.

class YourDetailView(DetailView):
     breadcrumbs = ['dashboard', 'list', 'detail']
     (...)

... 그리고 템플릿에서 :

<a href="/dashboard/" {% if 'dashboard' in view.breadcrumbs %}class="active"{% endif %}>Dashboard</a>
<a href="/list/" {% if 'list' in view.breadcrumbs %}class="active"{% endif %}>List</a>
<a href="/detail/" {% if 'detail' in view.breadcrumbs %}class="active"{% endif %}>Detail</a>

이것은 쉽고 깨끗한 솔루션이며 중첩 된 탐색과 잘 작동합니다.


이 예에서 세 가지 탐색 항목 모두가 .active아닐까요?
Oli

예, 그러나 이것은 일반적으로 다단계 탐색으로 달성하려는 것입니다. 물론 breadcrumbs원하는 경우 하나의 항목을 넣을 수 있습니다. 그러나 당신은 옳습니다-제 모범은 최고의 것이 아닙니다.
Konrad Hałas 2013 년

@Oli 개선 된 예.
Konrad Hałas 2013 년

9

특정 탐색 항목이 아닌 페이지의 본문 요소에 클래스 또는 ID를 적용 할 수 있습니다.

HTML :

<body class="{{ nav_class }}">

CSS :

body.home #nav_home,
body.about #nav_about { */ Current nav styles */ }

8

나는 이것을 이렇게한다 :

<a class="tab {% ifequal active_tab "statistics" %}active{% endifequal %}" href="{% url Member.Statistics %}">Statistics</a>

내가해야 할 일은 내 관점에서 {'active_tab': 'statistics'}컨텍스트 사전에 추가 하는 것입니다.

사용하는 경우 RequestContext템플릿의 현재 경로를 다음과 같이 가져올 수 있습니다.

{{ request.path }}

그리고 당신의 관점에서 :

from django.template import RequestContext

def my_view(request):
    # do something awesome here
    return template.render(RequestContext(request, context_dict))

이 정보를 공유해 주셔서 감사합니다. 이 방법을 사용했지만 탐색 모음에 플랫 페이지가 있으므로이를 감지하고 올바르게 강조 표시하기 위해 {% ifequal flatpage.url '/ about /'%}을 사용했습니다. 하드 코딩 된 URL 탐지가 마음에 들지 않지만 일회성 해킹에서는 작동합니다.
Matt Garrison

이 솔루션의 문제점은 "통계"를 코드에 하드 코딩 한 것입니다. 이것은 페이지의 URL을 얻기 위해 url 태그를 사용하는 목적을 무효화합니다.
저스틴

7

위의 nivhab에서 코드를 가져 와서 약간의 이상 함을 제거하고 깨끗한 템플릿 태그로 만들고 / account / edit /가 / account / 탭을 계속 활성화하도록 수정했습니다.

#current_nav.py
from django import template

register = template.Library()

@register.tag
def current_nav(parser, token):
    import re
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1])

class NavSelectedNode(template.Node):
    def __init__(self, url):
        self.url = url

    def render(self, context):
        path = context['request'].path
        pValue = template.Variable(self.url).resolve(context)
        if (pValue == '/' or pValue == '') and not (path  == '/' or path == ''):
            return ""
        if path.startswith(pValue):
            return ' class="current"'
        return ""



#template.html
{% block nav %}
{% load current_nav %}
{% url home as home_url %}
{% url signup as signup_url %}
{% url auth_login as auth_login_url %}
<ul class="container">
    <li><a href="{{ home_url }}"{% current_nav home_url %} title="Home">Home</a></li>
    <li><a href="{{ auth_login_url }}"{% current_nav auth_login_url %} title="Login">Login</a></li>
    <li><a href="{{ signup_url }}"{% current_nav signup_url %} title="Signup">Signup</a></li>
</ul>
{% endblock %}

6

이것은 위의 Toba가 제안한 CSS 솔루션의 변형 일뿐입니다.

기본 템플릿에 다음을 포함합니다.

<body id="section-{% block section %}home{% endblock %}">

그런 다음 기본 사용을 확장하는 템플릿에서 :

{% block section %}show{% endblock %}

그런 다음 css를 사용하여 본문 태그를 기반으로 현재 영역을 강조 표시 할 수 있습니다 (예 : ID가 nav-home 인 링크가있는 경우).

#section-home a#nav-home{
 font-weight:bold;
}


3

지금까지 답변 해 주셔서 감사합니다. 또 조금 다른 걸 봤는데 ..

내 템플릿에서 :

<li{{ link1_active }}>...link...</li>
<li{{ link2_active }}>...link...</li>
<li{{ link3_active }}>...link...</li>
<li{{ link4_active }}>...link...</li>

로직 (보통 urls.py)에서 내가 어떤 페이지에 있는지 확인한 class="selected"후에는 컨텍스트의 일부로 올바른 이름으로 템플릿에 전달합니다.

예 : link1 페이지에있는 경우 추가합니다. {'link1_active':' class="selected"'} 경우 템플릿의 컨텍스트에 하여 스쿠 핑 및 삽입합니다.

작동하는 것처럼 보이며 상당히 깨끗합니다.

편집 : 내 컨트롤러 /보기에서 HTML을 유지하기 위해 이것을 약간 수정했습니다.

<li{% if link1_active %} class="selected"{% endif %}>...link...</li>
<li{% if link2_active %} class="selected"{% endif %}>...link...</li>
...

템플릿의 가독성이 조금 떨어지지 만 URL 파일에서 원시 HTML을 푸시하지 않는 것이 좋습니다.


2
당신은해야 정말 이 기술이 요구하는 것입니다보기에 원시 HTML을 처리하지 마십시오. 사용자 정의 템플릿 태그 작성에 대해 생각해 보셨습니까?
Justin Voss

네가 옳아. HTML 통과를 중지하도록 편집했습니다. 이제 True를 통과합니다. 아직 템플릿 태그를 작성하지 않았지만 예, 시작하기에 좋은 곳이 될 수 있습니다.
Oli

2

루프를 통해 동적으로 생성되는 동일한 페이지에 여러 메뉴가 있습니다. 컨텍스트와 관련된 위의 게시물은 저에게 빠른 수정을 제공했습니다. 이것이 누군가를 돕기를 바랍니다. (활성 템플릿 태그와 함께이 태그를 사용합니다. 수정하면 동적 문제가 해결됩니다.) 어리석은 비교처럼 보이지만 작동합니다. 변수 이름을 active_something-unique 및 something-unique로 지정했습니다. 이런 식으로 중첩 된 메뉴에서 작동합니다.

다음은 뷰의 일부입니다 (내가 수행하는 작업을 충분히 이해할 수 있음).

def project_list(request, catslug):
    "render the category detail page"
    category = get_object_or_404(Category, slug=catslug, site__id__exact=settings.SITE_ID)
    context = {
        'active_category': 
            category,
        'category': 
            category,
        'category_list': 
            Category.objects.filter(site__id__exact=settings.SITE_ID),

    }

그리고 이것은 템플릿에서 가져온 것입니다.

<ul>
  {% for category in category_list %}
    <li class="tab{% ifequal active_category category %}-active{% endifequal %}">
      <a href="{{ category.get_absolute_url }}">{{ category.cat }}</a>
    </li>
  {% endfor %}
</ul>

2

내 솔루션은 요청 경로에 따라 변수를 설정하는 간단한 컨텍스트 프로세서를 작성하는 것이 었습니다.

def navigation(request):
"""
Custom context processor to set the navigation menu pointer.
"""
nav_pointer = ''
if request.path == '/':
    nav_pointer = 'main'
elif request.path.startswith('/services/'):
    nav_pointer = 'services'
elif request.path.startswith('/other_stuff/'):
    nav_pointer = 'other_stuff'
return {'nav_pointer': nav_pointer}

(settings.py의 TEMPLATE_CONTEXT_PROCESSORS에 사용자 지정 프로세서를 추가하는 것을 잊지 마십시오.)

그런 다음 기본 템플릿에서 링크 당 ifequal 태그를 사용하여 "활성"클래스를 추가할지 여부를 결정합니다. 이 접근 방식은 경로 구조의 유연성으로 엄격하게 제한되지만 비교적 겸손한 배포에 적합합니다.


글로벌 컨텍스트에서 이러한 기능을 사용하는 것이 정말 합리적이라고 생각하므로 다양한 방법으로 사이트 섹션을 참조 할 수 있습니다 (예 : 다른 사이트 섹션에 대해 다른 템플릿 사용). +1.
shacker

2

나는 nivhab의 포스트에 대한 나의 사소한 향상을 공유하고 싶었습니다. 내 응용 프로그램에는 하위 탐색이 있고 CSS 만 사용하여 숨기고 싶지 않았기 때문에 항목에 대한 하위 탐색을 표시할지 여부를 표시하려면 일종의 "if"태그가 필요했습니다.

from django import template
register = template.Library()

@register.tag
def ifnaviactive(parser, token):
    nodelist = parser.parse(('endifnaviactive',))
    parser.delete_first_token()

    import re
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:], nodelist)

class NavSelectedNode(template.Node):
    def __init__(self, patterns, nodelist):
        self.patterns = patterns
        self.nodelist = nodelist

    def render(self, context):
        path = context['request'].path
        for p in self.patterns:
            pValue = template.Variable(p).resolve(context)
            if path == pValue:
                return self.nodelist.render(context)
        return ""

기본적으로 활성 태그와 동일한 방식으로 사용할 수 있습니다.

{% url product_url as product %}

{% ifnaviactive request product %}
    <ul class="subnavi">
        <li>Subnavi item for product 1</li>
        ...
    </ul>
{% endifnaviactive %}

2

원래 솔루션의 또 다른 개선점입니다.

이것은 여러 패턴을 허용하며 다음과 같이 ' "'로 래핑 된 상대 URL로 작성된 이름없는 패턴도 가장 좋습니다.

{% url admin:clients_client_changelist as clients %}
{% url admin:clients_town_changelist as towns %}
{% url admin:clients_district_changelist as districts %}

<li class="{% active "/" %}"><a href="/">Home</a></li>
<li class="{% active clients %}"><a href="{{ clients }}">Clients</a></li>
{% if request.user.is_superuser %}
<li class="{% active towns districts %}">
    <a href="#">Settings</a>
    <ul>
        <li><a href="{{ towns }}">Towns</a></li>
        <li><a href="{{ districts }}">Districts</a></li>
    </ul>
</li>
{% endif %}

태그는 다음과 같습니다.

from django import template

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, urls):
        self.urls = urls

    def render(self, context):
        path = context['request'].path

        for url in self.urls:
            if '"' not in url:
                cpath = template.Variable(url).resolve(context)
            else:
                cpath = url.strip('"')

            if (cpath == '/' or cpath == '') and not (path == '/' or path == ''):
                return ""
            if path.startswith(cpath):
                return 'active'
        return ""

2

jquery를 사용하여 내 navbar를 강조 표시했습니다. 이 솔루션은 단순히 css 선택기에 맞는 항목에 "active"css 클래스를 추가합니다.

<script type="text/javascript" src="/static/js/jquery.js"></script>
<script>
    $(document).ready(function(){
        var path = location.pathname;
        $('ul.navbar a.nav[href$="' + path + '"]').addClass("active");
    });
</script>

2

태그 없이 @tback 의 답변 보다 약간 향상되었습니다 %if%.

# navigation.py
from django import template
from django.core.urlresolvers import resolve

register = template.Library()

@register.filter(name="activate_if_active", is_safe=True)
def activate_if_active(request, urlname):
  if resolve(request.get_full_path()).url_name == urlname:
    return "active"
  return ''

다음과 같이 템플릿에서 사용하십시오.

{% load navigation %}
<li class="{{ request|activate_if_active:'url_name' }}">
  <a href="{% url 'url_name' %}">My View</a>
</li>

그리고 설정에 포함 "django.core.context_processors.request"하십시오 TEMPLATE_CONTEXT_PROCESSORS.


2

가장 좋은 방법은 포함 태그를 사용하는 것입니다.

templates/fnf/nav_item.html

<li class="nav-item">
    <a class="nav-link {% if is_active %}active{% endif %}" href="{% url url_name %}">{{ link_name }}</a>
</li>

이것은 렌더링하려는 기본 부트 스트랩 탐색 항목입니다.

href 값과 선택적으로 link_name 값을 가져옵니다. is_active현재 요청을 기반으로 계산됩니다.

templatetags/nav.py

from django import template

register = template.Library()


@register.inclusion_tag('fnf/nav_item.html', takes_context=True)
def nav_item(context, url_name, link_name=None):
    return {
        'url_name': url_name,
        'link_name': link_name or url_name.title(),
        'is_active': context.request.resolver_match.url_name == url_name,
    }

그런 다음 탐색에서 사용하십시오. templates/fnf/nav.html

{% load nav %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
        <ul class="navbar-nav mr-auto">
                {% nav_item 'dashboard' %}
            </ul>

단순한 읽기이지만 URL 에서 정확히 일치하는 것으로 제한되지 않습니까? 나는 일반적으로 딥 페이지에도 이와 같은 탐색 힌트를 사용합니다. 당신이 중 하나에 있다면 예는 정보 탐색 항목이 강조 될 것이다 /about/company-history/또는 /about/what-we-do/
OLI

1
예,하지만 is_active교체 할 수 있으며 사전에 추가 된 다른 키가 반환됩니다. 또한 수표는 context.request.resolver_match.url_name.startswith(x)또는 다른 것일 수 있습니다 . 또한 dict 값을 설정하기 위해 return 문 앞에 코드가있을 수 있습니다. 또한, 서로 다른 템플릿, 즉 하나를 사용할 수 있습니다 top_level_nav.html다른 논리 등으로
Tjorriemorrie

깨끗하고 간단한 솔루션 ... 좋습니다!
mmw

1

Andreas의 대답을 약간 수정하면 urls.py에서 템플릿 태그로 경로 이름을 전달할 수있는 것 같습니다. 내 예에서는 my_tasks템플릿 태그 함수에서 reverse 함수를 사용하여 URL이 무엇인지 파악한 다음 요청 객체의 URL과 일치시킬 수 있습니다 (템플릿 컨텍스트에서 사용 가능).

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

register = template.Library()

@register.tag
def active(parser, token):
    args = token.split_contents()
    template_tag = args[0]
    if len(args) < 2:
        raise template.TemplateSyntaxError, "%r tag requires at least one argument" % template_tag
    return NavSelectedNode(args[1:])

class NavSelectedNode(template.Node):
    def __init__(self, name):
        self.name = name

    def render(self, context):

        if context['request'].path == reverse(self.name[1]):
            return 'active'
        else:
            return ''

urls.py

url(r'^tasks/my', my_tasks, name = 'my_tasks' ),

template.html

<li class="{% active request all_tasks %}"><a href="{% url all_tasks %}">Everyone</a></li>

어쩌면, 더 간단한 방법 : turnkeylinux.org/blog/django-navbar
jgsogo

1

내가 파티에 늦었다는 걸 알아. 그래도 인기있는 솔루션이 마음에 들지 않았습니다.

블록 방법 잘못된 것 같다 내가 탐색 자체가 포함되어야한다고 생각합니다.

template_tag 방법 잘못된 것 같다 내가하지 내가 먼저 URL 태그에서 URL을 얻을 가지고있다. 또한 css-class는 태그가 아닌 템플릿에 정의되어야한다고 생각합니다.

따라서 위에서 설명한 단점이없는 필터를 작성했습니다. TrueURL이 활성 상태이면 반환 되므로 다음과 함께 사용할 수 있습니다 {% if %}.

{% load navigation %}
<li{% if request|active:"home" %} class="active"{% endif %}><a href="{% url "home" %}">Home</a></li>

코드:

@register.filter(name="active")
def active(request, url_name):
    return resolve(request.path_info).url_name == url_name

그냥 확실히 사용할 수 있도록 RequestContext탐색 페이지 또는 요청 context_processor 수 있도록하기 위해settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'django.core.context_processors.request',
)

1

나는 jpwatts ', 110j 's, nivhab 's & 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 페이지 또는 루트 페이지에 대한 문제가 더 이상 없습니다.


1

솔루션 에서 영감을 받아이 접근 방식을 사용하기 시작했습니다.

**Placed in templates as base.html**

{% block tab_menu %}
<ul class="tab-menu">
  <li class="{% if active_tab == 'tab1' %} active{% endif %}"><a href="#">Tab 1</a></li>
  <li class="{% if active_tab == 'tab2' %} active{% endif %}"><a href="#">Tab 2</a></li>
  <li class="{% if active_tab == 'tab3' %} active{% endif %}"><a href="#">Tab 3</a></li>
</ul>
{% endblock tab_menu %}

**Placed in your page template**

{% extends "base.html" %}

{% block tab_menu %}
  {% with active_tab="tab1" %} {{ block.super }} {% endwith %}
{% endblock tab_menu %}

0

여기에 내 방법이 있습니다. 내 탐색 구조 (일부 메타 데이터가 포함 된 평면)를 포함하는 내 뷰에서 클래스를 구현했습니다. 그런 다음 이것을 템플릿에 주입하고 렌더링합니다.

내 솔루션은 i18n을 다룹니다. 아마도 좀 더 추상화해야 할 것 같지만 실제로는 그다지 신경 쓰지 않았습니다.

views.py :

from django.utils.translation import get_language, ugettext as _


class Navi(list):
    items = (_('Events'), _('Users'), )

    def __init__(self, cur_path):
        lang = get_language()
        first_part = '/' + cur_path.lstrip('/').split('/')[0]

        def set_status(n):
            if n['url'] == first_part:
                n['status'] == 'active'

        for i in self.items:
            o = {'name': i, 'url': '/' + slugify(i)}
            set_status(o)
            self.append(o)

# remember to attach Navi() to your template context!
# ie. 'navi': Navi(request.path)

다음과 같이 포함을 사용하여 템플릿 논리를 정의했습니다. 기본 템플릿 :

{% include "includes/navigation.html" with items=navi %}

실제 포함 (includes / navigation.html) :

 <ul class="nav">
     {% for item in items %}
         <li class="{{ item.status }}">
             <a href="{{ item.url }}">{{ item.name }}</a>
         </li>
     {% endfor %}
 </ul>

누군가가 유용하다고 생각하기를 바랍니다! 중첩 된 계층 구조 등을 지원하도록 그 아이디어를 확장하는 것이 매우 쉬울 것 같습니다.


0

포함 템플릿 "intranet / nav_item.html"을 만듭니다.

{% load url from future %}

{% url view as view_url %}
<li class="nav-item{% ifequal view_url request.path %} current{% endifequal %}">
    <a href="{{ view_url }}">{{ title }}</a>
</li>

nav 요소에 포함합니다.

<ul>
    {% include "intranet/nav_item.html" with view='intranet.views.home' title='Home' %}
    {% include "intranet/nav_item.html" with view='crm.views.clients' title='Clients' %}
</ul>

그리고 이것을 설정에 추가해야합니다.

from django.conf import global_settings
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
    'django.core.context_processors.request',
)

0

여기에 매우 간단한 솔루션이 있습니다. https://github.com/hellysmile/django-activeurl


1
여기,이 사이트에 답변의 유용한 포인트를 게시해야합니다. 그렇지 않으면 게시물이 "답변이 아님" 으로 삭제 될 위험이 있습니다. 원하는 경우 링크를 계속 포함 할 수 있지만 '참조'로만 사용할 수 있습니다. 대답은 링크가 필요없이 그 자체로 있어야합니다.
Andrew Barber

0

SO 질문에서

{% url 'some_urlpattern_name' as url %}
<a href="{{url}}"{% if request.path == url %} class="active"{% endif %}>Link</a>

각 링크에 대해 필요에 따라 반복합니다.


이것은 직접 일치에만 적용됩니다. 대부분의 탐색 시스템은 하위 페이지도 활성화 된 경우 탐색 항목을 활성으로 표시합니다. 즉 /blog/posts/2021/04/12, URL이면 / blog / nav 항목이 활성화됩니다.
Oli

@Oli 예, 몇 번 작동하지 않습니다. 유래 탐색 즉, 예를 들면 Questions, Tags, Users, Badges, Unanswered, Ask Question. 에서는 작동하지 Questions않지만 다른 모든 탐색에서는 제대로 작동합니다.
suhailvs

0

또한 jQuery를 사용하여 강조 표시하고 의미없는 Django 템플릿 태그로 템플릿을 어지럽히는 것보다 더 우아하다는 것을 알았습니다.

아래 코드는 부트 스트랩 3의 중첩 된 드롭 다운과 함께 작동합니다 (부모 <li>요소 와 하위 요소 모두 강조 표시됨) .

// DOM Ready
$(function() {
    // Highlight current page in nav bar
    $('.nav, .navbar-nav li').each(function() {
        // Count the number of links to the current page in the <li>
        var matched_links = $(this).find('a[href]').filter(function() {
            return $(this).attr('href') == window.location.pathname; 
        }).length;
        // If there's at least one, mark the <li> as active
        if (matched_links)
            $(this).addClass('active');
    });
});

템플릿 / html 마크 업을 변경하지 않고도 현재 페이지에 대한 click이벤트 를 추가 return false(또는 href속성을로 변경)하는 것도 매우 쉽습니다 #.

        var matched_links = $(this).find('a[href]').filter(function() {
            var matched = $(this).attr('href') == window.location.pathname;
            if (matched)
                $(this).click(function() { return false; });
            return matched;
        }).length;

0

클래스 기반 뷰를 위해이 믹스 인의 조합을 사용합니다.

class SetActiveViewMixin(object):
    def get_context_data(self, **kwargs):
        context = super(SetActiveViewMixin, self).get_context_data(**kwargs)
        context['active_nav_menu'] = {
            self.request.resolver_match.view_name: ' class="pure-menu-selected"'
        }
        return context

템플릿에서 다음과 같이하십시오.

<ul>
    <li{{active_nav_menu.node_explorer }}><a href="{% url 'node_explorer' '' %}">Explore</a></li>
    <li{{active_nav_menu.node_create }}><a href="{% url 'node_create' path %}">Create</a></li>
    <li{{active_nav_menu.node_edit }}><a href="{% url 'node_edit' path %}">Edit</a></li>
    <li{{active_nav_menu.node_delete }}><a href="{% url 'node_delete' path %}">Delete</a></li>
</ul>

0

Mine은 이전에 제출 된 다른 JS 접근 방식과 약간 비슷합니다. jQuery없이 ...

base.html에 다음이 있다고 가정합니다.

<div class="pure-u-1 pure-menu pure-menu-open pure-menu-horizontal header" >
    <ul class="">
        <li id="home"><a href="{% url 'article:index' %}">Home</a></li>
        <li id="news"><a href="{% url 'article:index' %}">News</a></li>
        <li id="analysis"><a href="{% url 'article:index' %}">Analysis</a></li>
        <li id="opinion"><a href="{% url 'article:index' %}">Opinion</a></li>
        <li id="data"><a href="{% url 'article:index' %}">Data</a></li>
        <li id="events"><a href="{% url 'article:index' %}">Events</a></li>
        <li id="forum"><a href="{% url 'article:index' %}">Forum</a></li>
        <li id="subscribe"><a href="{% url 'article:index' %}">Subscribe</a></li>
    </ul>
    <script type="text/javascript">
        (function(){
            loc=/\w+/.exec(window.location.pathname)[0];
            el=document.getElementById(loc).className='pure-menu-selected';         
        })();   
    </script>
</div>

특정 URL 패턴을 따르도록 계층 구조를 만들었습니다. 호스트 주소 다음에 ... 기본 카테고리 (예 : 집, 뉴스, 분석 등)가 있고 정규식은 위치에서 첫 번째 단어를 가져옵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.