HTMX within Django – Intro 2023

Mika, from Palmy Investing
4 min readMay 10, 2023

--

Photo by Hal Gatewood on Unsplash

Hello everyone! In this post I will show you how to use HTMX within your current django project.

Prerequirements:

  • Knowledge in django (e.g. you‘ve done the official tutorial)
  • Frotnend experience (Css& Html with django templates is enough)

Installing& Config

To get started you need to install django_htmx:

python -m pip install django-htmx

Afterwards we configure django-htmx:

# settings.py

INSTALLED_APPS = [
...,
"django_htmx",
...,
]


MIDDLEWARE = [
...,
"django_htmx.middleware.HtmxMiddleware",
...,
]

Next step is to load htmx. We currently only have a working django package without the ability to actually utilize HTMX.

Download the following raw javascript and create a new file called htmx.js inside your static directory

https://unpkg.com/htmx.org@1.9.2/dist/htmx.min.js

Then open your base.html or index.html or however you‘ve named your root html file, which is used via {% extends %}. If you have multiple of them f.ex. on a per app base – open all of them.

Moreover set the following inside the <body> tag. This is a best practice because you often want to refresh a page automatically because of condition x:

<head>

{% load static %}
<script src="{% static ‘htmx.min.js' %}" defer></script>

</head>

<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
...
</body>

Example/Use case

Refreshing is a good starting point. Let‘s dive into the django code, which automatically refresh a page on condition x:

from django_htmx.http import HttpResponseClientRefresh

def random_view(request):
"""An oversimplified view"""

if not request.GET.get("paramter"):
pass

elif request.htmx and len(request.GET.get("paramter")) > 32:
# Avoid too long hx-get requests with "parameter" in request path
return HttpResponseClientRefresh()

return render(request, "my_random_template.html", {})

The condition x is a length check of out ‘parameter’ url kwarg. An hx-get request to something like:

https://test.com/random?parameter=asdasdasddadasdasdasdasdasdasdasdasdasdsadasdasdasdasdasdada

will result in an auto refresh and your url will be:

https://test.com/random

Wait … hx-get?

Yes. Hx-get is used to call an htmx request with the GET method. Moreover we have:

  • hx-delete: Htmx to use DELETE request
  • hx-post: Htmx to use POST request

With django-htmx one can identify an htmx request via request.htmx. Therefore we are able to render 2 different templates within 1 view, based on the request method (htmx or regular)

from django_htmx.http import HttpResponseClientRefresh

def random_view(request):
"""An oversimplified view"""

if not request.GET.get("paramter"):
pass

elif request.htmx and len(request.GET.get("paramter")) > 32:
# Avoid too long hx-get requests with "parameter" in request path
return HttpResponseClientRefresh()

elif request.htmx and len(request.GET.get("paramter")) < 32:
return TemplateResponse(request, "partial_random.html", {"length_input": len(request.GET.get("parameter"))})

return render(request, "my_random_template.html", {})

The example above renders partial_random.html whenever the request was done via HTMX and the kwarg (parameter) has a correct length. Our template my_random_template.html has to follow some rules. Check this out:

<form hx-get="{% url 'your_url_name' %}" hx-target="#HTMXResults">
<input type="text" name="parameter" placeholder="Present your input (32 characters)">
<input type="submit" value="submit">
</form>

<div class="results" id="HTMXResults">

</div>

Here we use some hx-attributes:

  • hx-get as mentioned before to use request.htmx with GET
  • hx-target is the html id which we want to change. We fill HTMXResults with our partial template, therefre you can imagine that your partial will be rendered inside this div
  • name=“parameter“ is important, because for our example it sets the kwarg parameter in the url path, so that we are able to access it inside our vews.py

Some common mistakes

  • Within our example we want to render a template called partial_random.html, and this template should not have the {% extends %}, or at least not the same as my_random_template.html
  • Make sure that partial_random is exclusively partial, e.g. that you do not include a <body> tag etc. instead you should use as many divs, graphics and tables as you want
  • Dont overuse HTMX. Its intuitive as long as the user has a better experience, do not program 1 big view with douzands of possible HTMX requests.
  • Be careful with HttpResponseClientRefresh. Test if its possible to end up in an infinitve refresh loop – this is not what clients want and a critical bug in terms of UX.

The best resource

The best way to learn more about HTMX is to check out their examplesa and usecases. Start with hx-delete or lazy loading. Its possible to do everything thats mentioned there within django!

More articles about htmx?

Just comment and I will write more about HTMX + Django. Based on your feedback I could start a small series that deals with integrating all the examples for a sample django project.

Outro

Thanks for reading and make sure to follow my project – Palmy Investing – if you are interested in financial data and quantitative asset research.

--

--

Mika, from Palmy Investing
Mika, from Palmy Investing

Written by Mika, from Palmy Investing

Independent Author. Web tech. topics, will cover more niche topics once fun/time is available.