Django POST request is empty

Question:

Running Django 4.1.1. Having this code below in template. By clicking a button it sends a data to delete apropriate marker.

<form method="POST">
    {% csrf_token %}
    <ol>
        {% for marker in markers %}
            <li>
                {{ marker }} - <button class="button btn-primary" id="delete" value="{{ marker.pk }}" type="submit">Delete</button>
            </li>
        {% endfor %}
    </ol>
</form>

In views.py

def user_markers(request):
    markers = Marker.objects.filter(owner_id=request.user.id).select_related()
    if request.method == "POST":
        print(request.POST.get("delete"))  # gives me None
        marker = Marker.objects.get(pk=request.POST.get("delete"))
        marker.delete()
    context = {
        "markers": markers,
    }
    return render(request, "hub/markers.html", context)

The problem is that request.POST.get("delete") is empty.
POST data has only ‘csrfmiddlewaretoken’
Do I miss something?

Asked By: Vitalii Mytenko

||

Answers:

You need to specify this as name, so:

<button class="button btn-primary" id="delete" name="delete" value="{{ marker.pk }}" type="submit">Delete</button>

If you do not specify a name, it will not be include in the POST data, and thus it will not contain any value that is passed with the button.

You might want to improve the view function:

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect


@login_required
def user_markers(request):
    markers = Marker.objects.filter(owner_id=request.user.id).select_related()
    if request.method == 'POST':
        get_object_or_404(
            Marker, owner=request.user, pk=request.POST.get('delete')
        ).delete()
        return redirect('name-of-some-view')  # need to redirect
    context = {
        'markers': markers,
    }
    return render(request, 'hub/markers.html', context)

Note: In case of a successful POST request, you should make a redirect
[Django-doc]

to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.


Note: You can limit views to a view to authenticated users with the
@login_required decorator [Django-doc].


Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.

Answered By: Willem Van Onsem
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.