There are some methods for updating whole or usually a part of a web page using Javascript, Ajax or jQuery. Is there any alternative way to update a part of a web page? Answer is yes! We can do it using Htmx.
Htmx is a useful method to build modern user interfaces with the simplicity and power of hypertext. Not only updates a part of a page but Htmx also can do some other useful things. If you are looking for a Javascript alternative in some cases look at htmx docs.
How to use Htmx in Django
We will update a part of a page using Htmx in this exmaple. You can find this method in Htmx's docs as polling.
overview
template ---- page.html
---- refresh.html
views.py ---- PageView
---- RefreshView
urls.py ----- path for page.html/PageView
----- path for refresh.html/RefreshView
Add Htmx to django project
The fastest way to get going with htmx is to load it via a CDN. Add this script to each template we want or base.html template.
page.html :
...
{% block footer_script %}
<script src="https://unpkg.com/htmx.org@1.8.0"></script>
{% endblock footer_script %}
...
Add Htmx to templates
Create a <div></div> to hold part of the page which we want updating it using Htmx automatically without refreshing whole page.
page.html :
...
<div hx-get="/refresh" hx-trigger="every 3s">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Code</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
...
In page.html we defined "evey 3 s" in hx-trigger as interval time. Client's browser will send a get request to /refresh url every 3 seconds.
Then write Html and Django codes which we want replaced in the defined <div></div> periodically.
refresh.html :
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Code</th>
</tr>
</thead>
<tbody>
{% for i in prisoners %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td>{{ i.name }}</td>
<td>{{ i.code }}</td>
</tr>
{% endfor %}
</tbody>
</table>
We created an empty table in page.html then update it every 3 seconds using refresh.html with new records.
Update urls.py for Htmx
Create 2 different urls for page.html and refresh.html.
urls.py:
...
from .views import PageView, RefreshView
...
urlpatterns = [
...
path("page", PageView.as_view(), name="page"),
path("refresh", RefreshView.as_view(), name="refresh-page"),
]
...
How to stop Htmx polling in Django
Htmx sends get request to refresh url every 3 seconds in our example as interval time. It will send a get request from client's browser periodically, We can see it in inspect mode of our browser in network tab. Docs says:
If you want to stop polling from a server response you can respond with the HTTP response code
286
and the element will cancel the polling.
views.py :
...
class PageView(TemplateView):
"""View for result page which updates using htmx"""
template_name = "page.html"
#use your get function here.
...
class RefreshView(TemplateView):
"""View for returning new results based on htmx"""
template_name = "refresh.html"
def get(self, request, *args, **kwargs):
#your view logic here
...
if progress == 100: #stop htmx
return self.render_to_response(context, status=286)
else:
return self.render_to_response(context, status=200)
Client's browser sends get to RefreshView periodically untill server responses with a 286 status code which means stop!