HTMX within Django – Intro 2023
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.