[Django] Highlight Current Page Link (class='active')

How to add class="active" into HTML tag according to the URL of current page:

Settings

Because we need to access request context in template, so add the following settings if you haven’t.

1
2
3
4
5
6
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.static',
'django.core.context_processors.request',
'django.core.context_processors.media',
'django.contrib.auth.context_processors.auth'
)

Template Tags

Create templatetags directory with common_tags.py under APP_NAME:

I only use simple string matching (if stringA in stringB: ...). Feel free to modify if you want to use RegExp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 # APP_NAME/templatetags/common_tags.py
from django import template
from django.core.urlresolvers import reverse

register = template.Library()

@register.simple_tag()
def is_active(request, *url_strings):
for urlpattern in url_strings:
if urlpattern in request.path:
return 'active'
return ''

@register.simple_tag
def is_active_reverse(request, *urlnames):
for urlname in urlnames:
if reverse(urlname) in request.path:
return "active"
return ""

@register.simple_tag
def is_active_resolve(request, *urlnames):
resolver_match = resolve(request.path)
for urlname in urlnames:
if resolver_match.url_name == urlname:
return "active"
return ""

Using in Template

First, add:

1
{% load common_tags %}

at the top of your template file.

Read the code and you will know what they mean and the differences among the three tags:

By URL

1
<a href="{{ child.get_absolute_url }}" class="{% is_active request child.get_absolute_url %}">

By URL Name & reverse()

1
2
3
<li class="{% is_active_reverse request 'show_current_user_profile' %}">
<a href="{% url 'show_current_user_profile' %}">My account</a>
</li>

But in many condition, reverse() is very hard/inconvenient to use if the URL pattern needs pk or other kwargs. So we use another more universal way, resolve():

By URL Name & resolve()

1
2
<a class="{% is_active_resolve request 'all_products' 'products_under_category' %}"
href="{% url 'all_products' %}">Manage products</a>

resolve() needs only URL name, without pk or so.

Notice the three tags can accept multiple arguments (all_products, products_under_category).


[2015-03-07 土 16:06]
[2015-05-10 日 22:52] Update: add is_active_resolve, Some modification in descriptions, Make tags able to accept multiple arguments.
[2015-05-10 日 23:27] Done!!!!!!!!!!!!!!! ˊ・ω・ˋ