How to pass a parameter to a view with HTMX and Django?

Viewed 1740

I am trying to implement kind of a like-button with Django and htmx using django-htmx,but I do not know how how to pass the id as a parameter to my view in order to save the related item.

# models.py
class Item(models.Model):
    name = models.CharField()
    like = models.BooleanField(null=True, default=None)

The (simplified) table shows items like this:

id  name    like
--  -----   ----
 1  Alpha   None
 2  Beta    None

The idea is by klicking e.g. on the first "None", Django should change the like-value for the first item in the database to "True" and this should be reflected in the table:

id  name    like
--  -----   ----
 1  Alpha   True
 2  Beta    None

The table is generated by a template like this:

<table>
{% for item in page_obj %}
    <tr>
        <td>{{ item.id }}</td>
        <td>{{ item.name }}</td>
        <td id="like-{{ item.id }}"
            hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
            hx-post="{% url 'save-like' %}?id={{ item.id }}"
            hx-target="#like-{{ item.id }}" 
            hx-swap="outerHTML">
            {{ item.like }}
        </td>
    </tr>
{% endfor %}
</table>

With a click on "None", there is a request to the following function:

#views.py
def save_like(request):
    success = False
    if request.method == 'POST':
        item = Item.objects.filter(pk=request.POST['id']).first()
        item.like == True
        item.save()
        success = True
    if success:
        return HttpResponse('<td>True</td>>')
    else:
        return HttpResponse("Error")

My problem: request.POST is empty and I do not know how to pass the id to the function. (I do not understand how this parameter thing works with htmx: https://htmx.org/docs/#parameters )

Does anybody has a hint for me?

1 Answers

You've sent your id in url query params as ?id=1 not in request body. Query params can be accessed from request.GET

item_id = request.GET.get('id')

If you want to send id in request body add a hidden input field, and add hx-include="[name='id']" to include that field

<td id="like-{{ item.id }}"
            hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
            hx-post="{% url 'save-like' %}"
            hx-target="#like-{{ item.id }}" 
            hx-include="[name='id']"
            hx-swap="outerHTML">

  <input type="hidden" value="{{item.id}}" name="id">
  {{ item.like }}
</td>

Then you can access from request.POST['id']

Related