HTMX & Django

Florian Demmer

Django Meetup, 2024-01-16

Intermission

SummitLynx ist ein weltweit verfügbares digitales Gipfel- und Tourenbuch für Wanderer und Alpinisten.

www.summitlynx.com

... suchen Unterstützung für Modernisierung und Weiterentwicklung des Frontend Stack.

HTMX in 100 Seconds

django-htmx

  • by Adam Johnson (adamchainz)
  • Does not include HTMX itself
  • HtmxMiddleware ( request.htmx)
  • HTTP helper/tools
  • Debug Error Response Handler
  • Example Project & Tips

Provide & Configure HTMX

https://unpkg.com/browse/htmx.org/dist/

{% load static %}
<!-- 
  avoid CDN for privacy and performance reasons 
  https://blog.wesleyac.com/posts/why-not-javascript-cdn
-->
<script src="{% static 'js/htmx/htmx.min.js' %}" defer></script>
<!-- optionally add HTMX extensions -->
<script src="{% static 'js/htmx/debug.js' %}" defer></script>

<!-- example configuration -->
<meta name="htmx-config" content='{"historyCacheSize": 15}'>

<!-- enable/disable extension -->
<div hx-ext="debug">
    <button hx-post="/do">Debug me!</button>
    <button hx-post="/do" hx-ext="ignore:debug">Send it!</button>
</div>

HtmxMiddleware

def my_view(request):
    # serve partial if HTMX made the request
    # HX-Request
    if request.htmx:  # HtmxDetails
        template_name = "partial.html"
    else:
        template_name = "complete.html"
    return render(template_name, ...)
  
  
def get_secret_partial(request):
    if not request.user.is_authenticated:
        # use current URL in the browser, instead of request.path
        # HX-Current-URL
        next_url = request.htmx.current_url_abs_path or ""
        return HttpResponseClientRedirect(
            f"{settings.LOGIN_URL}?next={next_url}"
        )

HTTP helper/tools

def get_secret_partial(request):
    if not request.user.is_authenticated:
        next_url = request.htmx.current_url_abs_path or ""
        # Trigger client-side redirect, instead of redirect()
        # HX-Redirect
        return HttpResponseClientRedirect(
            f"{settings.LOGIN_URL}?next={next_url}"
        )

      
# <div hx-get="/news" hx-trigger="every 2s"></div>
def my_pollable_news_view(request):
    if event_finished():
        # make HTMX stop polling
        # HTTP status code 286
        return HttpResponseStopPolling()

Error Response Handler

document.addEventListener("htmx:beforeOnLoad", function (event) {
  const xhr = event.detail.xhr;
  if (xhr.status == 500 || xhr.status == 404) {
    // Tell htmx to stop processing this response
    event.stopPropagation();
    // Replace the page with response content
    document.children[0].innerHTML = xhr.response;
  }
});
{% load django_htmx %}
<!doctype html>
<html>
  ...
  <script src="{% static 'js/htmx/htmx.min.js' %}" defer></script>
  {% django_htmx_script %}
  </body>
</html>

django-htmx

  • Example Project
  • Tips

All the things

https://htmx.org

https://htmx.org/extensions

https://django-htmx.readthedocs.io

  https://blog.wesleyac.com/posts/why-not-javascript-cdn

  • 🐘  https://wien.rocks/@fdemmer

  • 📜  https://slides.com/fdemmer

Django Meetup, 2024-01-16

By Florian Demmer

Django Meetup, 2024-01-16

  • 57