python 43 lines · 7 steps

Active nav-link template tags in Django

Two custom template tags reverse a URL name and mark the link active when it matches the current request path.

Explained by highlit
1from django import template
2from django.urls import reverse, NoReverseMatch
3from django.utils.html import format_html
4 
5register = template.Library()
6 
7 
8@register.simple_tag(takes_context=True)
9def nav_link(context, url_name, label, css_class="nav-link", **kwargs):
10 request = context["request"]
11 
12 try:
13 target = reverse(url_name, kwargs=kwargs or None)
14 except NoReverseMatch:
15 target = url_name
16 
17 is_active = request.path == target or (
18 target != "/" and request.path.startswith(target)
19 )
20 
21 classes = css_class
22 if is_active:
23 classes = f"{css_class} active"
24 
25 aria = ' aria-current="page"' if is_active else ""
26 
27 return format_html(
28 '<a href="{}" class="{}"{}>{}</a>',
29 target,
30 classes,
31 template.Template(aria).render(template.Context()) if aria else "",
32 label,
33 )
34 
35 
36@register.simple_tag(takes_context=True)
37def active_class(context, url_name, css_class="active", **kwargs):
38 request = context["request"]
39 try:
40 target = reverse(url_name, kwargs=kwargs or None)
41 except NoReverseMatch:
42 return ""
43 return css_class if request.path.startswith(target) else ""
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Custom template tags with takes_context=True can read the current request to make rendering decisions.
  2. 2Reversing a URL name and comparing it against request.path is the standard way to detect the active navigation item.
  3. 3format_html safely composes HTML while treating interpolated values as untrusted, unlike raw string formatting.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Active nav-link template tags in Django — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code