Navigation in django

后端 未结 30 1244

I\'ve just done my first little webapp in django and I love it. I\'m about to start on converting an old production PHP site into django and as part its template, there is a

相关标签:
30条回答
  • 2020-11-27 09:56

    I just wanted to share my minor enhancement to nivhab's post. In my application I have subnavigations and I did not want to hide them using just CSS, so I needed some sort of "if" tag to display the subnavigation for an item or not.

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

    You can use this basically in the same way as the active tag:

    {% url product_url as product %}
    
    {% ifnaviactive request product %}
        <ul class="subnavi">
            <li>Subnavi item for product 1</li>
            ...
        </ul>
    {% endifnaviactive %}
    
    0 讨论(0)
  • 2020-11-27 09:56

    I've seen jpwatts', 110j's, nivhab's & Marcus Whybrow's answers, but they all seem to lack in something: what about the root path ? Why it's always active ?

    So I've made an other way, easier, which make the "controller" decides by itself and I think it resolve most of the big problems.

    Here is my custom tag:

    ## myapp_tags.py
    
    @register.simple_tag
    def nav_css_class(page_class):
        if not page_class:
            return ""
        else:
            return page_class
    

    Then, the "controller" declares CSS classes needed (in fact, the most important is it declares its presence to the template)

    ## views.py
    
    def ping(request):
        context={}
        context["nav_ping"] = "active"
        return render(request, 'myapp/ping.html',context)
    

    And finally, I render it in my navigation bar:

    <!-- 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>
    ...
    

    So each page has its own nav_css_class value to set, and if it's set, the template renders active: no need of request in template context, no URL parcing and no more problems about multi-URL pages or root page.

    0 讨论(0)
  • 2020-11-27 09:56

    **

    Just add url and name in jinja format like this

    **

     <ul class="nav navbar-nav">
            <li>
               <a href="{% url 'index' %}">Cities</a>
            </li>
            <li>
               <a href="{% url 'all_cafes' %}">Cafes</a>
            </li>
        </ul>
    
    0 讨论(0)
  • 2020-11-27 09:57

    You could apply a class or id to the body element of the page, rather than to a specific nav item.

    HTML:

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

    CSS:

    body.home #nav_home,
    body.about #nav_about { */ Current nav styles */ }
    
    0 讨论(0)
  • 2020-11-27 09:57

    I found the best is to use an inclusion tag:

    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>
    

    This is just my basic bootstrap nav item I wish to render.

    It gets the href value, and optionally the link_name value. is_active is calculated based on the current request.

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

    Then use it in a nav: 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>
    
    0 讨论(0)
  • 2020-11-27 09:58

    I liked the cleanness of 110j above so I took most of it and refactored to solve the 3 problems I had with it:

    1. the regular expression was matching the 'home' url against all others
    2. I needed multiple URLs mapped to one navigation tab, so I needed a more complex tag that takes variable amount of parameters
    3. fixed some url problems

    Here it is:

    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>
    
    0 讨论(0)
提交回复
热议问题