8

I'm implementing a bootstrap navbar as show in this example here

Items in a navbar are <li>'s , the "selected" item has the attribute class="active":

  <li class="active"> <a href="#"> Link1 </a> </li>
  <li>                <a href="#"> Link2 </a> </li>

In Django these items will be within a template, which gets included by any templates that are supposed to display the navbar. I'm thinking about doing it this way:

<li> <a href="/"        class="{% if template_name == "home.djhtml"    %}active{% endif %}"> Home    </a> </li>
<li> <a href="about/"   class="{% if template_name == "about.djhtml"   %}active{% endif %}"> About   </a> </li>
<li> <a href="contact/" class="{% if template_name == "contact.djhtml" %}active{% endif %}"> Contact </a> </li>

I would like to know if there is a built-in way to get the template_name (that is, the template being rendered, as passed to render_to_response(), in views.py)

Sure, I could explicitly add a template_name variable to render_to_response(), which would solve the problem. But thinking about DRY I feel this shouldn't be needed.

E.Z.
  • 6,393
  • 11
  • 42
  • 69

4 Answers4

14

I usually use a custom template tag for this use case of adding a class to the active tab, menu item, etc.

@register.simple_tag
def active_page(request, view_name):
    from django.core.urlresolvers import resolve, Resolver404
    if not request:
        return ""
    try:
        return "active" if resolve(request.path_info).url_name == view_name else ""
    except Resolver404:
        return ""

And here's a snippet from the top nav:

<ul class="nav">
    <li class="{% active_page request "about" %}"><a href="{% url "about" %}">About</a></li>
    ...
</ul>
Kevin Stone
  • 8,831
  • 41
  • 29
  • Thanks. How should I access the `request` object: pass it to `render()` as a `dictionary` variable? – E.Z. Oct 09 '13 at 11:45
  • 1
    This is how: http://stackoverflow.com/questions/702592/django-request-in-template – slumtrimpet Oct 09 '13 at 13:19
  • @slumtrimpet has it. It's provided by `RequestContext` assuming you're using it in your template rendering (Django Class Based Views do so automatically). – Kevin Stone Oct 09 '13 at 18:04
  • 1
    actually you should use here `resolve(request.path_info).view_name` instead of `url_name` if you're using url namespaces – ambi Apr 19 '16 at 19:49
3

I use:

class="{% if 'about' in request.path %}active{% endif %}"

It's a little shorter and more robust if the URI changes, just watch out if more than one path uses about.

renejsum
  • 69
  • 7
1

There is a much faster way, without creating any custom template tag!

<ul class = 'nav'>
    <li class="{% ifequal request.path 'about/'%} active {% endifequal%}">
        <a href="{% url "about" %}">About</a>
    </li>
</ul>

just be aware about request.path. It might be with slash symbol at the beginning or without at the end of the path!

prog.Dusan
  • 1,324
  • 2
  • 12
  • 25
0

Appending prog.Dusans answer for Django 1.7

settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth'
)

views.py
from django.shortcuts import render

def index(request):
    return render(request, 'index.html')

template
{% ifequal request.path '/pathname'%}active{% endifequal%}

Best is to add it to the base template so you need only to do it once.

Like I this version more than Kevin Stones because you have to add almost equal code to the template and don't need a template tag after all.

Community
  • 1
  • 1
sharpshadow
  • 1,256
  • 1
  • 9
  • 9