Swap & render_nav

This section covers the primary primitives used to render partials and orchestrate out-of-band updates in Django views.

Swaps (htmx_nav.swaps)

Swap: an out-of-band or <hx-partial> fragment rendered alongside the main content of an HTMX response.

class htmx_nav.swaps.Swap(template_name=None, context=None, content=None, target_id=None, swap_style='innerHTML', wrap=None, include_if=True)[source]

Bases: object

Represents an out-of-band (OOB) or <hx-partial> fragment for HTMX responses.

Parameters:
  • template_name (str | None) – Path to the template or partial (e.g., "nav.html#sidebar"). Mutually exclusive with content. Required unless creating a delete swap or content is provided.

  • content (str | None) – Ready-made fragment body, bypassing template rendering. Auto-escaped like a template variable unless wrapped in mark_safe. Mutually exclusive with template_name.

  • context (Mapping[str, Any] | None) – Context mapping for the fragment. Also serves as fallback context during full-page renders. Ignored when content is set.

  • target_id (str | None) – Target DOM element ID. If None, renders without auto-wrapping.

  • swap_style (str) – HTMX swap strategy ("innerHTML", "outerHTML", "delete", etc.).

  • wrap (Optional[Literal['oob', 'hx-partial']]) – Auto-wrap mode ("oob" or "hx-partial"). Defaults to the HTMX_NAV_DEFAULT_SWAP_WRAP setting. Ignored when swap_style="delete".

  • include_if (str | Callable[[HttpRequest], bool] | bool) – Predicate determining if the swap applies to the request.

Raises:

ValueError – If both or neither of template_name and content are provided, or if target_id is omitted for a delete swap.

Example

# Standard partial swap
Swap("partials/sidebar.html", {"active": "home"}, target_id="sidebar")

# Static string swap
Swap.text("badge-count", "5")

# Conditional deletion
Swap.delete("flash-banner", include_if=targeting("main"))
applies_to(request)[source]

Evaluate include_if against the request to determine inclusion.

Parameters:

request (HttpRequest) – The incoming HTTP request.

Return type:

bool

Returns:

True if this swap applies to the request.

content = None
context = None
classmethod delete(target_id, include_if=True)[source]

Build an OOB delete swap that removes target_id from the DOM.

Equivalent to <div id="{target_id}" hx-swap-oob="delete"></div>.

Parameters:
  • target_id (str) – DOM element ID to remove.

  • include_if (str | Callable[[HttpRequest], bool] | bool) – Predicate determining if the swap applies to the request.

Return type:

Swap

Returns:

A Swap configured for deletion.

include_if = True
render(request, parent_context=None, using=None)[source]

Render the swap to an HTML string.

Parameters:
  • request (HttpRequest) – The incoming HTTP request.

  • parent_context (Mapping[str, Any] | None) – Optional parent context to merge with swap context.

  • using (str | None) – Optional template engine name.

Return type:

str

Returns:

The rendered HTML string, auto-wrapped if target_id is set.

swap_style = 'innerHTML'
target_id = None
template_name = None
classmethod text(target_id, content, swap_style='innerHTML', wrap=None, include_if=True)[source]

Build a swap from a ready-made string, skipping template rendering.

Parameters:
  • target_id (str) – Target DOM element ID.

  • content (str) – The fragment body.

  • swap_style (str) – HTMX swap strategy.

  • wrap (Optional[Literal['oob', 'hx-partial']]) – Auto-wrap mode. Defaults to the HTMX_NAV_DEFAULT_SWAP_WRAP setting.

  • include_if (str | Callable[[HttpRequest], bool] | bool) – Predicate determining if the swap applies to the request.

Return type:

Swap

Returns:

A Swap that renders content directly.

wrap = None
htmx_nav.swaps.Swaps

Type alias for a single Swap, list/tuple of Swaps, or None. :meta hide-value:

Shortcuts (htmx_nav.shortcuts)

Rendering shortcuts for HTMX navigation.

htmx_nav.shortcuts.render_nav(request, template_name, context=None, content_type=None, status=None, using=None, *, partial=<object object>, swaps=None, title=None)[source]

Render a Django template with HTMX partial resolution and OOB swaps.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • template_name (str) – Path to the full template containing partial blocks.

  • context (Mapping[str, Any] | None) – Optional template context.

  • content_type (str | None) – Optional response content type.

  • status (int | None) – Optional HTTP status code.

  • using (str | None) – Optional template engine.

  • partial (str | Callable[[HttpRequest], str | None] | Mapping[str | PartialResolver, str | Callable[[HttpRequest], bool] | bool] | PartialResolver | None | object) – Specifies which partial to render for HTMX requests. Can be a block name ("#content"), standalone path, callable, or dict mapping names to targets. When None, renders the full template. Defaults to the HTMX_NAV_DEFAULT_PARTIAL setting ("#content").

  • swaps (Swap | list[Swap] | tuple[Swap, ...] | None) – Additional out-of-band swaps to include.

  • title (str | None) – Optional page title. Overrides title context variable and injects a <title> element for HTMX requests.

Return type:

TemplateResponse

Returns:

A TemplateResponse with partial resolution and OOB swaps.

Notes

  • Adds HX-Request to the Vary header for proper caching.

  • Context from swaps is merged with main context (swap context wins).

  • Title injection is HTML-escaped.

Example

# Basic partial selection
return render_nav(
    request,
    "project/detail.html",
    {"project": project},
    partial="#tab_content",
)

# Multiple partial targets with swaps
return render_nav(
    request,
    "project/detail.html",
    {"project": project},
    partial={
        "#tab_content": targeting("tab-content"),
        "#main_content": targeting("main-content"),
        "#content": True,  # fallback
    },
    swaps=[
        Swap("partials/sidebar.html", target_id="sidebar"),
        Swap("partials/notification.html", target_id="flash"),
    ],
    title=project.name,
)