Django HTMX Readthedocs Io en Latest
Django HTMX Readthedocs Io en Latest
Release 1.17.3
Adam Johnson
1 Installation 3
2 Middleware 5
3 Extension Script 7
4 HTTP tools 9
5 Example Project 15
6 Tips 17
7 Changelog 19
Index 27
i
ii
django-htmx Documentation, Release 1.17.3
CONTENTS: 1
django-htmx Documentation, Release 1.17.3
2 CONTENTS:
CHAPTER
ONE
INSTALLATION
1.1 Requirements
1.2 Installation
INSTALLED_APPS = [
...,
"django_htmx",
...,
]
MIDDLEWARE = [
...,
"django_htmx.middleware.HtmxMiddleware",
...,
]
3
django-htmx Documentation, Release 1.17.3
django-htmx does not include htmx itself, since it can work with many different versions. It’s up to you to add htmx
(and any extensions) to your project.
{% load static %}
<script src="{% static 'htmx.min.js' %}" defer></script>
Note: Extensions
You can adapt the above steps to set up htmx’s extensions that you wish to use. Download them from htmx’s ext/
folder into your project, and include their script tags after htmx, for example:
{% load static %}
<script src="{% static 'js/htmx/htmx.min.js' %}" defer></script>
<script src="{% static 'js/htmx/debug.js' %}" defer></script>
4 Chapter 1. Installation
CHAPTER
TWO
MIDDLEWARE
class django_htmx.middleware.HtmxMiddleware
This middleware attaches request.htmx, an instance of HtmxDetails (below). Your views, and any following
middleware, can use request.htmx to switch behaviour for requests from htmx. The middleware supports both
sync and async modes.
See it action in the “Middleware Tester” section of the example project.
class django_htmx.middleware.HtmxDetails
This class provides shortcuts for reading the htmx-specific request headers.
__bool__()
True if the request was made with htmx, otherwise False. Detected by checking if the HX-Request header
equals true.
This behaviour allows you to switch behaviour for requests made with htmx:
def my_view(request):
if request.htmx:
template_name = "partial.html"
else:
template_name = "complete.html"
return render(template_name, ...)
Return type
bool
boosted: bool
True if the request came from an element with the hx-boost attribute. Detected by checking if the
HX-Boosted header equals true.
You can use this attribute to change behaviour for boosted requests:
def my_view(request):
if request.htmx.boosted:
# do something special
...
return render(...)
5
django-htmx Documentation, Release 1.17.3
>>> request.htmx.current_url
'https://example.com/dashboard/?year=2022'
>>> # assuming request.scheme and request.get_host() match:
>>> request.htmx.current_url_abs_path
'/dashboard/?year=2022'
if not sudo_mode_active(request):
next_url = request.htmx.current_url_abs_path or ""
return HttpResponseClientRedirect(f"/activate-sudo/?next={next_url}")
history_restore_request: bool
True if the request is for history restoration after a miss in the local history cache. Detected by checking if
the HX-History-Restore-Request header equals true.
prompt: str | None
The user response to hx-prompt if it was used, or None.
target: str | None
The id of the target element if it exists, or None. Based on the HX-Target header.
trigger: str | None
The id of the triggered element if it exists, or None. Based on the HX-Trigger header.
trigger_name: str | None
The name of the triggered element if it exists, or None. Based on the HX-Trigger-Name header.
triggering_event: Any | None
The deserialized JSON representation of the event that triggered the request if it exists, or None. This
header is set by the event-header htmx extension, and contains details of the DOM event that triggered the
request.
6 Chapter 2. Middleware
CHAPTER
THREE
EXTENSION SCRIPT
django-htmx comes with a small JavaScript extension for htmx’s behaviour. Currently the extension only includes a
debug error handler, documented below.
3.1 Installation
The script is served as a static file called django-htmx.js, but you shouldn’t reference it directly. Instead, use the
included template tags, for both Django and Jinja templates.
Load and use the template tag in your base template, after your htmx <script> tag:
{% load django_htmx %}
<!doctype html>
<html>
...
<script src="{% static 'js/htmx.min.js' %}" defer></script>{# or however you include␣
˓→htmx #}
{% django_htmx_script %}
</body>
</html>
First, load the tag function into the globals of your custom environment:
# myproject/jinja2.py
from jinja2 import Environment
from django_htmx.jinja import django_htmx_script
def environment(**options):
env = Environment(**options)
env.globals.update(
{
# ...
"django_htmx_script": django_htmx_script,
(continues on next page)
7
django-htmx Documentation, Release 1.17.3
Second, call the function in your base template, after your htmx <script> tag:
{{ django_htmx_script() }}
htmx’s default behaviour when encountering an HTTP error is to discard the response content. This can make it hard
to debug errors in development.
The django-htmx script includes an error handler that’s active when Django’s debug mode is on (settings.DEBUG
is True). The handler detects responses with 404 and 500 status codes and replaces the page with their content. This
change allows you to debug with Django’s default error responses as you would for a non-htmx request.
See this in action in the “Error Demo” section of the example project.
Hint: This extension script should not be confused with htmx’s debug extension, which logs DOM events in the
browser console.
FOUR
HTTP TOOLS
def sensitive_view(request):
if not sudo_mode.active(request):
return HttpResponseClientRedirect("/activate-sudo-mode/")
...
class django_htmx.http.HttpResponseClientRefresh
htmx will trigger a page reload when it receives a response with the HX-Refresh header.
HttpResponseClientRefresh is a custom response class that allows you to send such a response. It
takes no arguments, since htmx ignores any content.
For example:
def partial_table_view(request):
if page_outdated(request):
return HttpResponseClientRefresh()
...
9
django-htmx Documentation, Release 1.17.3
def my_pollable_view(request):
if event_finished():
return HttpResponseStopPolling()
...
def my_pollable_view(request):
if event_finished():
return render("event-finished.html", status=HTMX_STOP_POLLING)
...
django_htmx.http.push_url(https://www.scribd.com/response,%20url)
Set the HX-Push-Url header of response and return it. This header makes htmx push the given URL into the
browser location history.
Parameters
• response (_HttpResponse) – The response to modify and return.
• url (str | Literal[False]) – The (relative) URL to push, or False to prevent the lo-
cation history from being updated.
Return type
_HttpResponse
For example:
django_htmx.http.reswap(response, method)
Set the HX-Reswap header of response and return it. This header overrides the swap method that htmx will
use.
Parameters
• response (_HttpResponse) – The response to modify and return.
• method (str) – The swap method.
Return type
_HttpResponse
For example:
def employee_table_row(request):
...
response = render(...)
if employee.is_boss:
reswap(response, "afterbegin")
return response
django_htmx.http.retarget(response, target)
Set the HX-Retarget header of response and return it. This header overrides the element that htmx will swap
content into.
Parameters
• response (_HttpResponse) – The response to modify and return.
• target (str) – CSS selector to target.
Return type
_HttpResponse
For example:
@require_POST
def add_widget(request):
...
if form.is_valid():
# Rerender the whole table on success
response = render("widget-table.html", ...)
return retarget(response, "#widgets")
def end_of_long_process(request):
response = render("end-of-long-process.html")
return trigger_client_event(
response,
"showConfetti",
{"colours": ["purple", "red", "pink"]},
after="swap",
)
FIVE
EXAMPLE PROJECT
The django-htmx repository contains an example project, demonstrating use of django-htmx. Run it locally and check
out its source code to learn about using htmx with Django, and how django-htmx can help.
15
django-htmx Documentation, Release 1.17.3
SIX
TIPS
This page contains some tips for using htmx with Django.
If you use htmx to make requests with “unsafe” methods, such as POST via hx-post, you will need to make htmx
cooperate with Django’s Cross Site Request Forgery (CSRF) protection. Django can accept the CSRF token in a header,
normally X-CSRFToken (configurable with the CSRF_HEADER_NAME setting, but there’s rarely a reason to change it).
You can make htmx pass the header with its hx-headers attribute. It’s most convenient to place hx-headers on your
<body> tag, as then all elements will inherit it. For example:
Note this uses {{ csrf_token }}, the variable, as opposed to {% csrf_token %}, the tag that renders a hidden
<input>.
This snippet should work with both Django templates and Jinja.
For an example of this in action, see the “CSRF Demo” page of the example project.
For requests made with htmx, you may want to reduce the page content you render, since only part of the page gets
updated. This is a small optimization compared to correctly setting up compression, caching, etc.
You can use Django’s template inheritance to limit rendered content to only the affected section. In your view, set up
a context variable for your base template like so:
@require_GET
def partial_rendering(request: HttpRequest) -> HttpResponse:
if request.htmx:
base_template = "_partial.html"
(continues on next page)
17
django-htmx Documentation, Release 1.17.3
...
return render(
request,
"page.html",
{
"base_template": base_template,
# ...
},
)
{% extends base_template %}
{% block main %}
...
{% endblock %}
<!doctype html>
<html>
<head>
...
</head>
<body>
<header>
<nav>
...
</nav>
</header>
<main id="main">
{% block main %}{% endblock %}
</main>
</body>
<main id="main">
{% block main %}{% endblock %}
</main>
For an example of this in action, see the “Partial Rendering” page of the example project.
18 Chapter 6. Tips
CHAPTER
SEVEN
CHANGELOG
19
django-htmx Documentation, Release 1.17.3
20 Chapter 7. Changelog
django-htmx Documentation, Release 1.17.3
• Move documentation from the README to Read the Docs. Also expand it with sections on installing htmx, and
configuring CSRF.
Thanks to Ben Beecher for intial setup in PR #194.
• Add HttpResponseClientRefresh for telling htmx to reload the page.
Thanks to Bogumil Schube in PR #193.
• Support the HX-Boosted header, which was added in htmx 1.6.0. This is parsed into the request.htmx.
boosted attribute.
• Support the HX-History-Restore-Request header, which was added in htmx 1.2.0. This is parsed into the
request.htmx.history_restore_request attribute.
• Support the Triggering-Event header, which is sent by the event-header extension. This is parsed into the
request.htmx.triggering_event attribute.
• Stop distributing tests to reduce package size. Tests are not intended to be run outside of the tox setup in the
repository. Repackagers can use GitHub’s tarballs per tag.
22 Chapter 7. Changelog
django-htmx Documentation, Release 1.17.3
• Remove X-HTTP-Method-Override handling from HtmxMiddleware. This has not been needed since htmx
0.0.5, when use of the header was extracted to its method-override extension in htmx commit 2305ae.
• This version and those before explored what’s possible with htmx and django, but were not documented.
24 Chapter 7. Changelog
CHAPTER
EIGHT
• genindex
• modindex
• search
25
django-htmx Documentation, Release 1.17.3
H
history_restore_request
(django_htmx.middleware.HtmxDetails at-
tribute), 6
HTMX_STOP_POLLING (in module django_htmx.http), 10
HtmxDetails (class in django_htmx.middleware), 5
HtmxMiddleware (class in django_htmx.middleware), 5
HttpResponseClientRedirect (class in
django_htmx.http), 9
HttpResponseClientRefresh (class in
django_htmx.http), 9
HttpResponseLocation (class in django_htmx.http), 9
HttpResponseStopPolling (class in
django_htmx.http), 10
P
prompt (django_htmx.middleware.HtmxDetails at-
tribute), 6
push_url() (in module django_htmx.http), 11
R
reswap() (in module django_htmx.http), 11
retarget() (in module django_htmx.http), 12
T
target (django_htmx.middleware.HtmxDetails at-
tribute), 6
27