Django HTMX
django-htmx is a Python package that provides extensions for integrating Django with htmx. It simplifies building dynamic and interactive web applications by offering middleware, template tags, and HTTP response utilities, allowing developers to leverage htmx's capabilities without writing extensive JavaScript. The library is actively maintained with a regular release cadence, ensuring compatibility with recent Django and Python versions.
Warnings
- gotcha CSRF Token Handling for POST requests: HTMX requests do not automatically send Django's CSRF token, which is required for POST, PUT, and DELETE requests. Failure to include it will result in 403 Forbidden errors.
- gotcha HTMX.org JavaScript Library is Separate: `django-htmx` provides Python utilities and template tags to *include* its own extension script, but it does NOT bundle or serve the core `htmx.org` JavaScript library itself. You must explicitly include `htmx.org` in your templates.
- gotcha `HtmxMiddleware` is practically essential: While technically optional, most of the core features like `request.htmx` (used to detect htmx requests and access htmx-specific headers) rely on `HtmxMiddleware` being added to your `MIDDLEWARE` setting.
- gotcha Vary Headers for HTTP Caching: If your Django views render different HTML content for HTMX requests versus standard browser requests (using `if request.htmx:`), you must add `HX-Request` to the `Vary` header for proper HTTP caching behavior.
- breaking Removal of old template tags and mixins in 1.0.0: `{% htmx_script %}` (for htmx.org), `HTMXViewMixin`, `{% htmx_include %}`, and `{% htmx_attrs %}` were removed in `django-htmx` version 1.0.0. This was a significant breaking change for users upgrading from pre-1.0.0 versions.
- breaking Potential breaking changes in `htmx.org` 4.0+: While `django-htmx` is separate, the underlying `htmx.org` library is releasing major versions (e.g., 4.0), which may introduce breaking changes to its core API, extension system, or event handling, potentially impacting custom JavaScript or advanced integrations.
Install
-
pip install django-htmx
Imports
- HtmxMiddleware
from django_htmx.middleware import HtmxMiddleware
- request.htmx
if request.htmx: ...
- django_htmx_script
{% load django_htmx %} {% django_htmx_script %} - HttpResponseClientRedirect
from django_htmx.http import HttpResponseClientRedirect
- HttpResponseStopPolling
from django_htmx.http import HttpResponseStopPolling
Quickstart
import os
from django.shortcuts import render
from django.http import HttpResponse
# settings.py additions
# INSTALLED_APPS = [
# ...,
# 'django_htmx',
# ]
# MIDDLEWARE = [
# ...,
# 'django_htmx.middleware.HtmxMiddleware',
# ]
def my_view(request):
if request.htmx:
# This branch handles HTMX requests
return HttpResponse("<div>Updated content from HTMX!</div>")
else:
# This branch handles initial page load or regular requests
context = {'initial_message': 'Click the button below to update!'}
return render(request, 'my_template.html', context)
# my_template.html (within your templates directory, inheriting a base.html)
# Assuming base.html includes the htmx.org script and {% django_htmx_script %}
# and has <body hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
#
# {% load django_htmx %}
# <!DOCTYPE html>
# <html lang="en">
# <head>
# <meta charset="UTF-8">
# <title>Django HTMX Demo</title>
# <script src="https://unpkg.com/htmx.org@1.9.10"></script> <!-- or self-host -->
# {% django_htmx_script %}
# </head>
# <body hx-headers='{"x-csrftoken": "{{ csrf_token }}"}'>
# <div id="content">{{ initial_message }}</div>
# <button hx-get="/my-htmx-view/" hx-target="#content" hx-swap="innerHTML">Load HTMX Content</button>
# </body>
# </html>
# urls.py addition (example)
# from django.urls import path
# from . import views
#
# urlpatterns = [
# path('my-htmx-view/', views.my_view, name='my_htmx_view'),
# ]