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.