The new and improved {% active %} tag

A few months ago, I described a Django template tag that I wrote to identify the currently active page.

At the time, I was satisfied with my solution, and I must say that it worked perfectly for all these months. The one thing I didn’t like about it though was that it wasn’t DRY. I had to specify an regular expression in the tag that would identify the current page. Those regexes were usually a copy of the ones in my urls.py file. This caused me some head scratching a couple of times when I changed a URL regex in urls.py, but forgot to change it in my _nav.html template.

Today, I took the time to remedy the situation and I am satisfied enough with the result to share it.

import re
from django.core.urlresolvers import RegexURLResolver
from project.app import urls

@register.simple_tag
def active(request, view='', pattern=''):
    '''
    Return 'active' if *pattern* matches *request.path* (the current location
    in the browser). The empty string is returned otherwise.  The pattern is
    either given by the user or taken from the URLconf.

    *request* (required): an HttpRequest object
    *view*    (optional): a view name
    *pattern* (optional): a regular expression string
    '''
    path = request.path[1:] # Strip the leading /

    if view != '':
        for urlpattern in urls.urlpatterns:
            # Skip include()s, they don't have the _callback_str attribute.
            if isinstance(urlpattern, RegexURLResolver):
                continue

            if view == urlpattern._callback_str:
                pattern = urlpattern.regex
                break

    if pattern == '':
        return ''

    if re.search(pattern, path):
        return 'active'
    else:
        return ''

active takes two arguments: a request object and either a view name or a regex. If a view string is given, the function will try to find the matching regex in the urls module. If none can be found, the empty string is returned. If a regex pattern is given, this will be used to test the current path. This parameter exists to make sure that you can use any regular expression if you so desire. Leaving both parameters blank will return the empty string.

I hope this helps you.

3 Responses to “The new and improved {% active %} tag”

  1. Chris Says:

    any thoughts on making this work with dynamic URLs? I’ve tried to retrofit the django url tag, but I just don’t know enough python. Great work!

  2. Djangodude Says:

    not working with the latest version…

    need to import template
    from django import template

    and

    register = template.Library()

    And there are afew more problems am trying to figure out…

    gr,

    D.

  3. Personificator Says:

    For those of you wishing for a Django SVN ready version of this…
    place in /templatetags/

    import re
    from django import template
    from django.core.urlresolvers import RegexURLResolver
    from project.app import urls

    register = template.Library()

    @register.simple_tag
    def active(request, view=”, pattern=”):
    ”’
    Return ‘active’ if *pattern* matches *request.path* (the current location
    in the browser). The empty string is returned otherwise. The pattern is
    either given by the user or taken from the URLconf.

    *request* (required): an HttpRequest object
    *view* (optional): a view name
    *pattern* (optional): a regular expression string
    ”’
    path = request.path[1:] # Strip the leading /

    if view != ”:
    for urlpattern in urls.urlpatterns:
    # Skip include()s, they don’t have the _callback_str attribute.
    if isinstance(urlpattern, RegexURLResolver):
    continue

    if view == urlpattern._callback:
    pattern = urlpattern.regex
    break

    if pattern == ”:
    return ”

    if re.search(pattern, path):
    return ‘active’
    else:
    return ”

Leave a Reply