Reference

For class attributes, method signatures, and type information, see the API Reference.

This page documents the runtime behaviors that aren’t captured in the API docs.

Template Tag

{% load django_simple_nav %}
{% django_simple_nav nav [template_name="..."] %}

Argument

Required

Description

nav

yes

A dotted import path string to a Nav class (e.g. "config.nav.MainNav"), a dotted path to a callable that accepts request and returns a Nav (e.g. "config.nav.main_nav"), or a Nav instance from the template context. See Programmatic Navigation.

template_name

no

Override the template used to render the navigation. Passed as a keyword argument: template_name="my_template.html".

Expects request in the template context.

Jinja2 Function

See Jinja2 for setup and usage.

def django_simple_nav(nav: str | Nav, template_name: str | None = None) -> str:
    ...

Same arguments as the template tag. Must be registered in the Jinja2 environment’s globals.

Template Resolution

Nav.render() resolves the template through these methods, in order:

Method

Default behavior

Override to…

get_template(template_name=None)

Calls get_template_name() and loads the template from disk.

Return an inline template string, add caching, or customize loading.

get_template_name()

Returns self.template_name or raises ImproperlyConfigured.

Choose a template dynamically at runtime.

If get_template() returns a string instead of a template object, render() compiles it as an inline template using the configured template engine.

See Customizing Template Resolution for examples.

Template Context

The template specified by Nav.template_name receives:

Variable

Type

Description

items

list

Top-level navigation items.

Each item in the list exposes:

Variable

Type

Description

title

SafeString

The item’s title.

url

str

Resolved URL. Empty string for a NavGroup without a URL.

active

bool

Whether this item matches the current request.

items

list | None

Child items for NavGroup. None for NavItem.

extra_context keys

object

Any additional keys from extra_context.

Items are also self-rendering: {{ item }} renders the item using its own template. See Self-Rendering Items.

URL Resolution

When a url is provided, it is resolved in this order:

  1. Promise (e.g. reverse_lazy): converted to a string.

  2. Callable: called with no arguments; the return value is used.

  3. String: passed to django.urls.reverse(). If NoReverseMatch is raised, the string is used as a literal URL.

After resolution, the trailing slash is adjusted based on append_slash:

  • None: uses settings.APPEND_SLASH.

  • True: always appends a slash to the path.

  • False: never appends a slash to the path.

The slash logic applies only to the path component — query strings, fragments, and absolute URL schemes are preserved.

Active State

An item is considered active when its resolved URL matches the current request.

Condition

Rule

Path

Exact match only. No prefix matching.

Query parameters

Must match exactly (parsed as dictionaries).

Scheme and host

For absolute URLs, must match the request. Relative URLs compare only the path.

NavGroup

Active if its own URL matches or any descendant is active.

Permission Evaluation

See Permissions for practical examples.

Permissions are evaluated in order. All must pass (AND logic).

Permission type

How it’s checked

"is_anonymous", "is_authenticated", "is_active", "is_staff", "is_superuser"

Read as a boolean attribute on request.user.

"app.codename" (any other string)

Checked via request.user.has_perm().

Callable

Called with request; must return bool.

Special cases:

  • Superuser short-circuit: if request.user.is_superuser is True, all permission checks pass immediately.

  • No django.contrib.auth: all permission checks are skipped; every item is shown.

  • No request.user: items with permissions are hidden; items without permissions are shown.

Settings

DJANGO_SIMPLE_NAV = {
    "TEMPLATE_BACKEND": None,  # default
}

Key

Type

Default

Description

TEMPLATE_BACKEND

str | None

None

Full path of the template backend to use (e.g. "django.template.backends.django.DjangoTemplates"). When None, the first configured backend is used. Only relevant with multiple template backends.