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.