[Django]-DeleteView with confirmation template and POST method

3πŸ‘

I now found a solution: I basically add hidden input fields which again transport the IDs of the checked checkboxes on the POST request.

But if someone finds an even more elegant way, I’m open to suggestions. πŸ™‚

views.py

class SomeItemConfirmDeleteView(DeleteView):
    template_name = 'confirm_delete_someitems.html'
    model = SomeItem
    success_url = reverse_lazy('list_someitems_url')
    items_to_delete = []

    def get_queryset(self):
        queryset = super(ChargeParkConfirmDeleteView, self).get_queryset()
        self.queryset = queryset.filter(id__in=self.items_to_delete)
        return self.queryset

    def get_object(self, queryset=None):
        return self.get_queryset()

    def post(self, request, *args, **kwargs):
        self.items_to_delete = self.request.POST.getlist('itemsToDelete')
        if self.request.POST.get("confirm_delete"):
            # when confirmation page has been displayed and confirm button pressed
            queryset = self.get_queryset()
            queryset.delete() # deleting on the queryset is more efficient than on the model object
            return HttpResponseRedirect(self.success_url)
        elif self.request.POST.get("cancel"):
            # when confirmation page has been displayed and cancel button pressed
            return HttpResponseRedirect(self.success_url)
        else:
            # when data is coming from the form which lists all items
            return self.get(self, *args, **kwargs)

confirm_delete_someitems.html:

<form action="" method="post">
    {% csrf_token %}
    {% trans 'The following objects as well as their related objects will be deleted. Are you sure?' %}
    <ul>
        {% for item in object %}
            <input type="hidden" value="{{ item.id }}" name="itemsToDelete" />
            <li><a href="{{ item.get_absolute_url }}">{{ item }}</a></li>
        {% endfor %}
    </ul>
    <input type="submit" class="btn btn-primary" value="{% trans 'Confirm deletion' %}" name="confirm_delete" />
    <input type="submit" class="btn btn-primary" value="{% trans 'Cancel' %}" name="cancel"/>
</form>
πŸ‘€Marc

1πŸ‘

$(".delete-link").click(function(){
    confirm_box = confirm("Are you sure?");
    if(confirm_box == true)
        return true;
    else
        return false;
})

1πŸ‘

Thanks Marc

This was really helpful for me. I also wanted to get to a few generic class based views like DeleteView via post method. However, I had to change a few things and I want to add this here, if someone else with a limited knowledge of Python as me would search for a solution.

Part of my html template:

    <form method="post">{% csrf_token %}
                        <div class="form-group">
                                Sure, you want to delete that object?<br>
                                <br>
                                <strong>{{ object }}</strong>
                                {{ form.errors }}
                                <br>
                                <br>
                                <input type="hidden" name="confirm_delete" value="confirm_delete">
                                <button type="submit" class="btn btn-primary">Delete</button>
                        </div>
                </form>

and part of my views.py

class MV_Loeschen(DeleteView):
    template_name = templ_folder_name + 'mv_loeschen.html'
    model = MV
    success_url = reverse_lazy(url_app_name + 'mv_ausgabe_alle')

    def get_object(self, queryset=None):
        self.queryset = MV.objects.get(mv_id = self.to_delete)
        return self.queryset

    def post(self, request, mvpk):
        self.to_delete = mvpk
        if self.request.POST.get("confirm_delete"):
            queryset = MV.objects.get(mv_id = mvpk)
            queryset.delete()
            return HttpResponseRedirect(self.success_url)
        else:
            return self.get(self, mvpk)

So, what am I doing here? The def post() method explains to MV_Loeschen how to handle post requests. I receive a parameter mvpk from another page via post form where I tell Django that I want to go to a view in order to delete the MV object with id that is in mvpk.

Then I set self.to_delete to contain that id (mvpk). I need that later in another def. Then I have to see if I just reached the confirmation page (do you really want to delete that?) or if I already confirmed that I want to delete the object. The first case is handled by the else fork (or however you call that) at the the end. This seems to raise internally a call for the DeleteView, but using the GET method. So I looked this up at

https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView

and also the code in my python/site-packages/subfolders.

The def get in turn uses the get_object method. But this def get_object is unaware of mvpk/the id of my MV object. So, I get this from self.to_delete (therefore I needed to assign that before). Here I take a different approach than Marc.

As in his solution get_object() calls get_queryset(), which returns a queryset, and I did not understand the super-line in his solution, I just get the queryset directly here in get_object().

So back to def post(). In case I already confirmed that I want to delete that object, have to get that parameter. I do this with:

self.request.POST.get("confirm-delete")

Thanks again, Marc, I was wondering why I could not access:

request.POST['confirm-delete']

directly. I am not sure that I understood that entirely by now, but at least you helped me to get this working.

Then I might have a redundant line with the new setting of the queryset. I don’t know. And then I delete the queryset or the MV object respectively.

Finally I redirect to the success_url and had to import HttpResponseRedirect from django.http for that.

πŸ‘€MDoe

Leave a comment