Skip to main content

Extensions for using Django with htmx.

Project description

https://img.shields.io/github/workflow/status/adamchainz/django-htmx/CI/main?style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/django-htmx.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

Extensions for using Django with htmx.

Requirements

Python 3.7 to 3.10 supported.

Django 2.2 to 4.0 supported.


Want to work smarter and faster? Check out my book Boost Your Django DX which covers many ways to improve your development experience.


Installation

  1. Install with pip:

    python -m pip install django-htmx
  2. Add django-htmx to your INSTALLED_APPS:

    INSTALLED_APPS = [
        ...,
        "django_htmx",
        ...,
    ]
  3. Add the middleware:

    MIDDLEWARE = [
        ...,
        "django_htmx.middleware.HtmxMiddleware",
        ...,
    ]
  4. (Optional) Add the extension script to your template, as documented below.

It’s up to you to add htmx (and any extensions) to your project, via a <script> tag in your base template. For resilience, you probably want to download it into your project’s static files, rather than rely on the unpkg.com hosted version.

Example app

See the example app in the example/ directory of the GitHub repository for usage of django-htmx.

Reference

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.

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.

For Django Templates, load and use the template tag, after your htmx <script> tag:

{% load django_htmx %}
{% django_htmx_script %}

For Jinja Templates, you need to perform two steps. 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,
        }
    )
    return env

Second, call the function in your template, after your htmx <script> tag:

{{ django_htmx_script() }}

Debug Error Handler

htmx’s default behaviour when encountering an HTTP error is to discard the response. This can make it hard to debug errors in development.

The django-htmx script includes an error handler that’s active when debug mode is on. 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 app.

django_htmx.middleware.HtmxMiddleware

This middleware attaches request.htmx, an instance of HtmxDetails.

See it action in the “Middleware Tester” section of the example app.

django_htmx.middleware.HtmxDetails

This class provides shortcuts for reading the htmx-specific request headers.

__bool__(): bool

True if the request was made with htmx, otherwise False. This is based on the presence of the HX-Request header.

This allows you to switch behaviour for requests made with htmx like so:

def my_view(request):
    if request.htmx:
        template_name = "partial.html"
    else:
        template_name = "complete.html"
    return render(template_name, ...)

boosted: bool

True if the request came from an element with the hx-boost attribute. Based on the HX-Boosted header.

current_url: str | None

The current URL of the browser, or None for non-htmx requests. Based on the HX-Current-URL header.

history_restore_request: bool

True if the request is for history restoration after a miss in the local history cache. Based on the HX-History-Restore-Request header.

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 representtation 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.

django_htmx.http.HttpResponseClientRedirect: type[HttpResponse]

htmx can trigger a client side redirect when it receives a response with the HX-Redirect header. HttpResponseClientRedirect is a HttpResponseRedirect subclass for triggering such redirects.

For example:

from django_htmx.http import HttpResponseClientRedirect


def sensitive_view(request):
    if not sudo_mode.active(request):
        return HttpResponseClientRedirect("/activate-sudo-mode/")
    ...

django_htmx.http.HttpResponseStopPolling: type[HttpResponse]

When using a polling trigger, htmx will stop polling when it encounters a response with the special HTTP status code 286. HttpResponseStopPolling is a custom response class with that status code.

For example:

from django_htmx.http import HttpResponseStopPolling


def my_pollable_view(request):
    if event_finished():
        return HttpResponseStopPolling()
    ...

django_htmx.http.HTMX_STOP_POLLING: int

A constant for the HTTP status code 286, for use with e.g. Django’s render shortcut.

from django_htmx.http import HTMX_STOP_POLLING


def my_pollable_view(request):
    if event_finished():
        return render("event-finished.html", status=HTMX_STOP_POLLING)
    ...

django_htmx.http.trigger_client_event(response, name, *, params, after)

Full signature:

def trigger_client_event(
    response: HttpResponse,
    name: str,
    params: dict[str, Any],
    *,
    after: EventAfterType = "receive"
) -> None:
    ...

Modify the HX-Trigger headers of response to trigger client-side events. Takes the name of the event to trigger and any JSON-compatible parameters for it, and stores them in the appropriate header. Uses DjangoJSONEncoder for its extended data type support.

Which of the HX-Trigger headers is modified depends on the value of after:

  • "receive", the default, maps to HX-Trigger

  • "settle" maps to HX-Trigger-After-Settle

  • "swap" maps to HX-Trigger-After-Swap

Calling trigger_client_event multiple times for the same response and after will add or replace the given event name and preserve others.

For example:

from django_htmx.http import trigger_client_event


def end_of_long_process(request):
    response = render("end-of-long-process.html")
    trigger_client_event(
        response,
        "showConfetti",
        {"colours": ["purple", "red", "pink"]},
        after="swap",
    )
    return response

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-htmx-1.8.0.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_htmx-1.8.0-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file django-htmx-1.8.0.tar.gz.

File metadata

  • Download URL: django-htmx-1.8.0.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.1

File hashes

Hashes for django-htmx-1.8.0.tar.gz
Algorithm Hash digest
SHA256 a8d41e74b907b9b9491fc9af99cf9a4a2879f9e9eee26592d4baf84f5f5982e5
MD5 cd7a4e20376a5d08f68ea07b578535a5
BLAKE2b-256 57393c0736ec9a58bbbfae49139bddc282c102d31049b3f1c2b28992fa56f43b

See more details on using hashes here.

File details

Details for the file django_htmx-1.8.0-py3-none-any.whl.

File metadata

  • Download URL: django_htmx-1.8.0-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.1

File hashes

Hashes for django_htmx-1.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f84d10d346e7862cc46f25204ec3cddd8d48b0a93f3f7c234d1f75fa62bbea8a
MD5 c90951b87d5deb3d79acd1cd5cc9828e
BLAKE2b-256 b3e21fc7e004cf877313c3350cf03190e4d52979475ef0b72eb0309057902947

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page