Why htmx

Many pages only need a small live part: a search box, a "load more" button, an inline form. htmx covers that with HTML attributes: an element sends a request, the server returns an HTML fragment, htmx swaps it into the page. You keep Django views and templates, and there is no build step or JSON layer.

The htmx request cycle
The htmx request cycle
ApproachServer returnsClient code
Classicfull pagenone
htmxHTML fragmentone script, hx-* attributes
SPAJSONframework, state, build step

💡 Build the plain full-page version first. htmx then only improves it, and the site still works without JavaScript.

Setup

Install pip install django-htmx. The package adds request.htmx and helpers; the htmx library itself is loaded with a <script> tag.

python
# settings.py
INSTALLED_APPS = [
    # ...
    "django_htmx",
]

MIDDLEWARE = [
    # ...
    "django_htmx.middleware.HtmxMiddleware",
]
html
{% load django_htmx %}
<!doctype html>
<html lang="en">
<head>
  <script src="https://unpkg.com/htmx.org@2.0.4"></script>
  {% django_htmx_script %}
</head>
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
  {% block content %}{% endblock %}
</body>
</html>

hx-headers on <body> puts the CSRF token into every request. {% django_htmx_script %} shows error responses in the browser while DEBUG is on.

⚠️ django-htmx does not ship the htmx library. Add the script from a CDN or your static files.

Partial templates and search

Split a template into a full page and a fragment. The view returns the fragment when request.htmx is true.

python
# blog/views.py
from django.shortcuts import render

from .models import Post