Skip to main content

django-htmx-nav

PyPI Version Python Version Django Version htmx Version License: MIT

A lightweight helper library for Django + HTMX that keeps navigation UI synchronized with the URL, preventing stale sidebars, breadcrumbs, titles, and other surrounding elements.

Homepage · Documentation · Interactive Demo

The Problem

When an HTMX request updates a single container (like #content), regions outside that container, such as active sidebar items, breadcrumb trails, and badge counts, do not update automatically. The main content updates, but the surrounding navigation UI still reflects the previous route:

┌─────────────────────────────────────────────────────────────┐
│ Header / Breadcrumbs (Stale: Page 1)                        │
├──────────────┬──────────────────────────────────────────────┤
│ Sidebar      │  Main Content (Updated: Page 2)              │
│ (Stale)      │  Targeted element swapped; surrounding       │
│              │  navigation controls did not.                │
└──────────────┴──────────────────────────────────────────────┘

django-htmx-nav keeps these regions synchronized by making the URL the source of truth for navigation state regardless of whether it is an HTMX request or a full-page load.

Installation

pip install django-htmx-nav

How It Works

1. Automatic Partial Selection (render_nav)

Use render_nav as a drop-in replacement for Django's render(). Direct visits and full-page reloads render the complete template, while HTMX requests return the matching Django partial:

# views.py
from htmx_nav import render_nav

def project_list(request):
    projects = Project.objects.all()

    return render_nav(
        request,
        "projects/list.html",
        {"projects": projects},
    )
<!-- templates/projects/list.html -->
{% extends "base.html" %}

{% block content %}
{% partialdef content inline %}
  <div id="content">
    {% for project in projects %}
      <div>{{ project.name }}</div>
    {% endfor %}
  </div>
{% endpartialdef %}
{% endblock %}

2. Synchronizing Navigation UI (Swap)

Attach out-of-band swaps to update persistent navigation regions alongside the main response:

# views.py
from django.shortcuts import get_object_or_404
from htmx_nav import Swap, render_nav
from .models import Project

def project_detail(request, pk):
    project = get_object_or_404(Project, pk=pk)

    return render_nav(
        request,
        "projects/detail.html",
        {"project": project},
        swaps=[
            Swap(
                "components/_sidebar.html",
                {"active": project.id},
                target_id="sidebar",
            ),
            Swap(
                "components/_breadcrumbs.html",
                target_id="breadcrumbs",
            ),
        ],
        title=project.name,
    )

The title argument updates the document title during an HTMX navigation while also providing context["title"] during a full-page render.

3. Reusable Navigation Shells (make_shell_renderer)

Define recurring navigation updates once and reuse them across views:

# shells.py
from htmx_nav import Swap, make_shell_renderer

render_shell = make_shell_renderer(
    lambda request: [
        Swap("components/_sidebar.html", target_id="sidebar"),
        Swap("components/_breadcrumbs.html", target_id="breadcrumbs"),
    ]
)

# views.py
def ticket_detail(request, pk):
    ticket = get_object_or_404(Ticket, pk=pk)

    return render_shell(
        request,
        "tickets/detail.html",
        {"ticket": ticket},
        extra_swaps=Swap(
            "components/_status_badge.html",
            target_id="ticket-status",
        ),
    )

The shell renderer automatically includes the configured swaps whenever the view is rendered through it. extra_swaps lets individual views add their own out-of-band updates.

4. Class-Based Views

The same navigation shell can be reused with Django's generic class-based views through make_shell_view_mixin:

from django.views.generic import DetailView
from htmx_nav import Swap, make_shell_view_mixin

# Reuse the shell renderer defined above.
ShellViewMixin = make_shell_view_mixin(render_shell)


class ProjectBoardView(ShellViewMixin, DetailView):
    model = Project
    template_name = "pages/board.html"
    context_object_name = "project"

    def get_extra_swaps(self):
        return Swap(
            "components/_status_badge.html",
            target_id="project-status",
        )

Learn More

  • Quickstart Guide — Install the library and build your first URL-driven HTMX navigation flow.
  • Architectural Guide — Compare approaches to stale navigation and explore the decision tree for choosing an architecture.
  • Benchmark Experiments — Reproduce the benchmark comparing 8 implementation strategies, including MPA, vanilla HTMX, and django-htmx-nav, or explore the Dashboard for live reference results.

License

Released under the MIT License.

Metadata

Release files for django-htmx-nav 0.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-htmx-nav 0.3.3
File Size Uploaded Provenance Actions
django_htmx_nav-0.3.3.tar.gz 31.3 kB With provenance Details for django_htmx_nav-0.3.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-htmx-nav 0.3.3
File Interpreter ABI Platform Actions
django_htmx_nav-0.3.3-py3-none-any.whl Python 3 none any Details for django_htmx_nav-0.3.3-py3-none-any.whl

Total release size: 53.8 kB

Release files / django_htmx_nav-0.3.3.tar.gz

Download URL django_htmx_nav-0.3.3.tar.gz
Size 31.3 kB
Tags Source
SHA-256 checksum
How to use checksums
6c192dc88733aa5a88e36db6ac0cf29b67a2207bf7d41c6cd0e10d33cad80992
BLAKE2b-256 checksum
How to use checksums
5cc1f61dbeeac184e8a1cbe571fd5bfefa7c9cc46adf30bcc4e145a854ad881b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / django_htmx_nav-0.3.3-py3-none-any.whl

Download URL django_htmx_nav-0.3.3-py3-none-any.whl
Size 22.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f5cab27dd4ca9bc5e5bae520ad6b3cc432b71728662c9ceb2ff820e0b60b360e
BLAKE2b-256 checksum
How to use checksums
2f596c51754f8a136e7d0110138dfccd6a96c60c6dee191d53592fe07323c9e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Security for django-htmx-nav 0.3.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_htmx_nav-0.3.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page