Snippets and Examples¶
The extension contributes secure Django-first HTMX patterns for django-html documents.
Type a prefix to insert the snippet, then move through its editable placeholders.
Mutating forms include Django's CSRF token. The examples use HTMX syntax shared by the supported HTMX 2 and HTMX 4 catalogs. See Core Django response contracts for matching view and response examples.
Prefixes¶
| Prefix | Classification | Description |
|---|---|---|
htmx-get |
Common | Django URL-backed HTMX GET button |
htmx-post |
Common | CSRF-safe Django form submitted through HTMX |
htmx-delete |
Common | CSRF-safe Django delete form submitted through POST |
htmx-search |
Common | Debounced Django HTMX search input |
htmx-form-validation |
Common | Django form replaced with server-rendered validation state |
htmx-file-upload |
Curated recipe | CSRF-safe multipart file upload with a status target |
htmx-bulk-actions |
Curated recipe | CSRF-safe bulk action form for Django objects |
htmx-dependent-dropdown |
Curated recipe | Django select that loads options for a dependent field |
htmx-status-form |
Curated recipe | HTMX 4 Django form with status-specific validation handling |
htmx-infinite |
Common | Load the next Django page when revealed |
htmx-poll |
Curated recipe | Poll a Django view until work is complete |
htmx-lazy |
Common | Load a Django fragment when its placeholder appears |
htmx-boost-nav |
Curated recipe | Progressively enhance Django navigation with history updates |
htmx-progress |
Curated recipe | Poll server-rendered progress for a Django task |
htmx-click-to-edit |
Common | Replace a Django object summary with an edit form |
htmx-table-row |
Curated recipe | Replace a Django table row with server-rendered editing controls |
htmx-dialog |
Curated recipe | Load a script-free non-modal dialog from a Django view |
htmx-modal |
Curated recipe | Load a Django view into a fixed CSS-only modal overlay |
htmx-tabs |
Curated recipe | Replace server-rendered tabs and selected state |
htmx-morph |
Curated recipe | HTMX 4 state-preserving refresh |
htmx-oob-swap |
Common | Update a second region from a Django HTMX response |
htmx-toast |
Curated recipe | Append an accessible notification from an HTMX response |
htmx-partial-response |
Curated recipe | HTMX 4 response fragment with explicit target and swap |
partialdef |
Django 6 | Define a Django 6 template partial |
partialdef-inline |
Django 6 | Define and render an inline Django 6 template partial |
partial |
Django 6 | Render a same-file Django 6 template partial |
Requests and forms¶
htmx-get¶
Django URL-backed HTMX GET button.
Classification: Common
<button type="button" hx-get="{% url 'view-name' %}" hx-target="#content" hx-swap="innerHTML">
Load
</button>
Endpoint or context: The view returns the HTML fragment that should replace the selected target.
htmx-post¶
CSRF-safe Django form submitted through HTMX.
Classification: Common
<form method="post" action="{% url 'view-name' %}"
hx-post="{% url 'view-name' %}"
hx-target="#content" hx-swap="innerHTML">
{% csrf_token %}
<!-- Add content here. -->
</form>
Endpoint or context: The POST view validates the submitted fields and returns the replacement fragment for the selected target.
htmx-delete¶
CSRF-safe Django delete form submitted through POST.
Classification: Common
<form method="post" action="{% url 'delete-view' object.pk %}"
hx-post="{% url 'delete-view' object.pk %}"
hx-confirm="Are you sure?"
hx-target="closest .item"
hx-swap="outerHTML">
{% csrf_token %}
<button type="submit">Delete</button>
</form>
Endpoint or context: The POST view performs the deletion and returns either an empty response or replacement markup for the item.
htmx-search¶
Debounced Django HTMX search input.
Classification: Common
<input type="search" name="q"
hx-get="{% url 'search-view' %}"
hx-trigger="input changed delay:300ms, search"
hx-target="#results">
Endpoint or context: The search view reads the input value and returns the current result-list fragment.
htmx-form-validation¶
Django form replaced with server-rendered validation state.
Classification: Common
<form method="post" action="{% url 'validate-view' %}"
hx-post="{% url 'validate-view' %}"
hx-target="this" hx-swap="outerHTML">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
Endpoint or context: The view returns the complete bound form with HTTP 200 when invalid, or a complete success fragment when valid.
htmx-file-upload¶
CSRF-safe multipart file upload with a status target.
Classification: Curated recipe
<form method="post" action="{% url 'upload-view' %}" enctype="multipart/form-data"
hx-post="{% url 'upload-view' %}"
hx-encoding="multipart/form-data"
hx-target="#upload-result"
hx-swap="innerHTML" hx-indicator="#upload-indicator">
{% csrf_token %}
<label for="upload-file">Choose a file</label>
<input id="upload-file" type="file" name="file" required>
<button type="submit">Upload</button>
<span id="upload-indicator" class="htmx-indicator" role="status">Uploading…</span>
</form>
<div id="upload-result" aria-live="polite"></div>
Endpoint or context: The upload view reads request.FILES, validates the file, and returns success or error markup for the upload-result target.
htmx-bulk-actions¶
CSRF-safe bulk action form for Django objects.
Classification: Curated recipe
<form method="post" action="{% url 'bulk-view' %}"
hx-post="{% url 'bulk-view' %}"
hx-target="#items-body"
hx-swap="outerHTML">
{% csrf_token %}
<table>
<thead><tr><th scope="col">Select</th><th scope="col">Item</th></tr></thead>
<tbody id="items-body">
{% for object in objects %}
<tr>
<td><input type="checkbox" name="selected" value="{{ object.pk }}" aria-label="Select {{ object }}"></td>
<td>{{ object }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit">Apply to selected</button>
</form>
Endpoint or context: The POST view processes every selected value and returns a complete tbody element with the same id.
htmx-dependent-dropdown¶
Django select that loads options for a dependent field.
Classification: Curated recipe
<label for="parent-select">Category</label>
<select id="parent-select" name="category"
hx-get="{% url 'options-view' %}"
hx-trigger="change"
hx-target="#dependent-select"
hx-swap="innerHTML">
<!-- Add content here. -->
</select>
<label for="dependent-select">Option</label>
<select id="dependent-select" name="option"></select>
Endpoint or context: The options view reads the selected parent value and returns option elements for the dependent select.
htmx-status-form¶
HTMX 4 Django form with status-specific validation handling.
Classification: Curated recipe
<form method="post" action="{% url 'view-name' %}"
hx-post="{% url 'view-name' %}" hx-target="#result"
hx-status:422="swap:innerHTML target:#errors" hx-status:5xx="swap:none">
{% csrf_token %}
<div id="errors" role="alert"></div>
<!-- Add content here. -->
<button type="submit">Save</button>
</form>
<div id="result"></div>
Endpoint or context: Requires HTMX 4. Return validation HTML with status 422, and success HTML for the result container. Server error responses do not swap.
Loading and navigation¶
htmx-infinite¶
Load the next Django page when revealed.
Classification: Common
{% if page_obj.has_next %}
<div hx-get="?page={{ page_obj.next_page_number }}"
hx-trigger="revealed"
hx-target="this" hx-swap="outerHTML"
role="status">
Loading…
</div>
{% endif %}
Endpoint or context: The list view returns the next result fragment followed by a new next-page trigger when another page exists.
htmx-poll¶
Poll a Django view until work is complete.
Classification: Curated recipe
<div hx-get="{% url 'status-view' task.pk %}"
hx-trigger="every 5s"
hx-target="this"
hx-swap="outerHTML"
role="status" aria-live="polite">
Waiting…
</div>
Endpoint or context: The status view returns the same polling region while work continues and omits hx-trigger after completion.
htmx-lazy¶
Load a Django fragment when its placeholder appears.
Classification: Common
<section hx-get="{% url 'fragment-view' %}"
hx-trigger="load"
hx-target="this"
hx-swap="outerHTML"
aria-busy="true">
<p class="htmx-indicator" role="status">Loading…</p>
</section>
Endpoint or context: The fragment view returns the complete replacement section without aria-busy.
htmx-boost-nav¶
Progressively enhance Django navigation with history updates.
Classification: Curated recipe
<nav aria-label="Primary">
<a href="{% url 'home' %}" hx-boost="true"
hx-target="#main-content" hx-select="#main-content"
hx-swap="outerHTML" hx-push-url="true">Home</a>
<!-- Add content here. -->
</nav>
<main id="main-content" tabindex="-1"></main>
Endpoint or context: Each linked view returns a normal full page containing the same main-content element, which hx-select extracts.
htmx-progress¶
Poll server-rendered progress for a Django task.
Classification: Curated recipe
<div hx-get="{% url 'progress-view' task.pk %}"
hx-trigger="every 1s"
hx-target="this"
hx-swap="outerHTML"
role="status" aria-live="polite">
<label for="task-progress">Progress</label>
<progress id="task-progress" value="{{ task.progress }}" max="100">{{ task.progress }}%</progress>
</div>
Endpoint or context: The progress view returns updated markup and omits hx-trigger when the task reaches a terminal state.
Editing and UI¶
htmx-click-to-edit¶
Replace a Django object summary with an edit form.
Classification: Common
<article>
<h2>{{ object }}</h2>
<button type="button" hx-target="closest article" hx-swap="outerHTML" hx-get="{% url 'edit-view' object.pk %}">Edit</button>
</article>
Endpoint or context: The edit view returns a CSRF-protected form that targets and replaces itself after submission.
htmx-table-row¶
Replace a Django table row with server-rendered editing controls.
Classification: Curated recipe
<tr id="item-{{ object.pk }}">
<th scope="row">{{ object }}</th>
<td><button type="button" hx-target="closest tr" hx-swap="outerHTML" hx-get="{% url 'edit-view' object.pk %}">Edit</button></td>
</tr>
Endpoint or context: The edit view returns a complete replacement row containing a CSRF-protected update form.
htmx-dialog¶
Load a script-free non-modal dialog from a Django view.
Classification: Curated recipe
<button type="button" hx-get="{% url 'dialog-view' object.pk %}"
hx-target="#dialog"
hx-swap="outerHTML"
aria-controls="dialog">
Open dialog
</button>
<dialog id="dialog" aria-labelledby="dialog-title"></dialog>
Endpoint or context: The view returns a dialog with the same id, the open attribute, a labelled title, and a native method="dialog" close form; it is non-modal without showModal().
htmx-modal¶
Load a Django view into a fixed CSS-only modal overlay.
Classification: Curated recipe
<button type="button" hx-get="{% url 'modal-view' %}"
hx-target="#modal" hx-swap="innerHTML"
aria-haspopup="dialog" aria-controls="modal">
Open modal
</button>
<div id="modal" class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title"></div>
Endpoint or context: The modal view returns the overlay markup with underlay/close controls that target the same container and swap it empty to close; no JavaScript is required.
htmx-tabs¶
Replace server-rendered tabs and selected state.
Classification: Curated recipe
<section id="tabs" aria-label="Sections">
<nav role="tablist">
<a id="tabs-overview" role="tab" aria-selected="true"
aria-controls="tabs-panel"
href="{% url 'tabs-view' 'overview' %}"
hx-get="{% url 'tabs-view' 'overview' %}"
hx-target="#tabs" hx-swap="outerHTML" hx-push-url="true">
Overview
</a>
<!-- Add content here. -->
</nav>
<div id="tabs-panel" role="tabpanel" aria-labelledby="tabs-overview">
{{ tab_content }}
</div>
</section>
Endpoint or context: The tabs view returns the complete section with updated tablist, aria-selected state, and panel content.
htmx-morph¶
HTMX 4 state-preserving refresh.
Classification: Curated recipe
<section id="live-region" hx-get="{% url 'fragment-view' %}"
hx-trigger="every 5s" hx-swap="innerMorph">
<!-- Add content here. -->
</section>
Endpoint or context: Requires HTMX 4. The view returns the region contents. Use stable element IDs to help morphing preserve focus and state.
Server responses¶
htmx-oob-swap¶
Update a second region from a Django HTMX response.
Classification: Common
Endpoint or context: Return this fragment alongside the primary response; HTMX replaces the existing element with the matching id.
htmx-toast¶
Append an accessible notification from an HTMX response.
Classification: Curated recipe
<div id="notifications" hx-swap-oob="beforeend:#notifications">
<p role="status" aria-live="polite">Saved successfully.</p>
</div>
Endpoint or context: Return this fragment with a primary response to append its status message to the existing notifications region.
htmx-partial-response¶
HTMX 4 response fragment with explicit target and swap.
Classification: Curated recipe
Endpoint or context: Requires HTMX 4. Return one or more hx-partial elements to update multiple targets. This is an HTMX response element, separate from Django partialdef template tags.
Django partials¶
partialdef¶
Define a Django 6 template partial.
Classification: Django 6
Endpoint or context: Django 6 registers the named block as a reusable partial in the current template.
partialdef-inline¶
Define and render an inline Django 6 template partial.
Classification: Django 6
Endpoint or context: Django 6 registers and renders the named partial at its definition site.
partial¶
Render a same-file Django 6 template partial.
Classification: Django 6
Endpoint or context: The referenced partial must be defined in the same template or resolved through Django's supported partial syntax.