developer tip

장고 내비게이션

optionbox 2020. 8. 21. 07:35
반응형

장고 내비게이션


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

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

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

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


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

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 %}

그렇게하려면 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을 참조하십시오.


나는 위의 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>

저는 이 질문을 해결하기 위해 특별히 쓴 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


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>

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


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

HTML :

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

CSS :

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

나는 이것을 이렇게한다 :

<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))

위의 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 %}

이것은 위의 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;
}

적절한 매개 변수와 함께 reverse 함수사용 하여 현재 URL을 가져올 수 있습니다.


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

내 템플릿에서 :

<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을 푸시하지 않는 것이 좋습니다.


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

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

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 태그를 사용하여 "활성"클래스를 추가할지 여부를 결정합니다. 이 접근 방식은 경로 구조의 유연성으로 엄격하게 제한되지만 비교적 겸손한 배포에 적합합니다.


나는 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 %}

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

이것은 여러 패턴을 허용하며 다음과 같이 ' "'로 래핑 된 상대 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 ""

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>

태그 없이 @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.


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

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>

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>

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

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

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',
)

나는 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 페이지 또는 루트 페이지에 대한 문제가 더 이상 없습니다.


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

**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 %}

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

내 솔루션은 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>

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


포함 템플릿 "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',
)

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


SO 질문에서

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

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


또한 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;

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

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>

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

참고 URL : https://stackoverflow.com/questions/340888/navigation-in-django

반응형