Tips#
This page contains some tips for using htmx with Django.
Make htmx Pass the CSRF Token#
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:
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
...
</body>
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.
Partial Rendering#
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:
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from django.views.decorators.http import require_GET
@require_GET
def partial_rendering(request: HttpRequest) -> HttpResponse:
if request.htmx:
base_template = "_partial.html"
else:
base_template = "_base.html"
...
return render(
request,
"page.html",
{
"base_template": base_template,
# ...
},
)
Then in the template (page.html
), use that variable in {% extends %}
:
{% extends base_template %}
{% block main %}
...
{% endblock %}
Here, _base.html
would be the main site base:
<!doctype html>
<html>
<head>
...
</head>
<body>
<header>
<nav>
...
</nav>
</header>
<main id="main">
{% block main %}{% endblock %}
</main>
</body>
…whilst _partial.html
would contain only the minimum element to update:
<main id="main">
{% block main %}{% endblock %}
</main>
For an example of this in action, see the “Partial Rendering” page of the example project.