1

Here i have two forms within my single page.I have a list of categories info in some table and i have two different action with POST request.One is to delete the single category object and another is to delete the checked objects. But deleting the single object is not working after placing two forms together.Before there was no form for deleting selected categories so the deleting the single object was working fine with the modal but when i used two form then even if i click the delete single category link then it is performing the delete selected category view and says no category selected.

How can i handle two forms here.I have given two different names in a submit button and two different actions also.

def delete_category(request, pk):
    category = get_object_or_404(Category, pk=pk)
    if request.method == 'POST' and 'single-delete' in request.POST:
        category.delete()
        messages.success(request, '{} category deleted.'.format(category.title))
        return redirect('view_categories')
    else:
        messages.error(request,'Invalid request')


def delete_selected_categories(request):
    selected_categories = Category.objects.filter(id__in=request.POST.getlist('categories'))
    if selected_categories:
        if 'delete_selected' in request.POST:
            count = selected_categories.count()
            selected_categories.delete()
            messages.success(request, '{} categories deleted.'.format(count))
            return redirect('view_categories')
    else:
        messages.info(request, 'No categories selected.')
        return redirect('view_categories')

template

<div class="table-responsive">
                <form action ="{% url 'delete_selected_categories' %}" method="post">
                    {% csrf_token %}
              <table>
                {% for category in categories %}
                    <tr>
                        <td>

                          <input name ="categories" type="checkbox" id="category-{{category.pk}}" value="{{category.pk}}" >
                 <label for="category-{{category.pk}}">{{ forloop.counter }}</label>

                     </td>
                        <td>{{category.title}}</td>
                        <td>{{category.active}}</td>

                        <td>
                         <a type="button"  data-toggle="modal" data-target="#delete-modal">Delete</a>

                        </td>

                    </tr>
                 <div class="modal" id="delete-modal">
                          <div class="modal-dialog">
                            <div class="modal-content">

                              <div class="modal-header">
                                <h4 class="modal-title"> Are you sure you want to delete ?</h4>
                                <button type="button" class="close" data-dismiss="modal">&times</button>
                              </div>

                              <div class="modal-body">
                                <form method="POST" action="{% url 'delete_category' category.pk %}" id="delete-confirm-form">
                                        {% csrf_token %}
                                  <button name="single-delete" type="submit" class="btn btn-primary">Delete</button>

                                    <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
                                </form>
                              </div>
                            </div>
                          </div>
                        </div>

                {% endfor %}
                </tbody>

            </table>

               <button type="submit" name="delete_selected">
                  Delete Selected Categories

               </button>
                </form>
            </div>

1 Answers1

1

Your problem is that you have nested forms, which is not allowed in HTML. This probably leads to the single-delete button submitting the outer delete_selected_categories form.

To fix this, move the modals outside of the main form, like this:

<div class="table-responsive">
    <form action ="{% url 'delete_selected_categories' %}" method="post">
        {% csrf_token %}
        <table>
            {% for category in categories %}
                <tr>
                    <td>
                        <input name ="categories" type="checkbox" id="category-{{category.pk}}" value="{{category.pk}}" >
                        <label for="category-{{category.pk}}">{{ forloop.counter }}</label>
                    </td>
                    <td>{{category.title}}</td>
                    <td>{{category.active}}</td>

                    <td>
                        <a type="button"  data-toggle="modal" data-target="#delete-modal">Delete</a>
                    </td>
                </tr>
            {% endfor %}
            </tbody>

        </table>

        <button type="submit" name="delete_selected">
            Delete Selected Categories
        </button>
    </form>

    {%  for category in categories %}
        <div class="modal" id="delete-modal">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title"> Are you sure you want to delete ?</h4>
                        <button type="button" class="close" data-dismiss="modal">&times</button>
                    </div>
                    <div class="modal-body">
                        <form method="POST" action="{% url 'delete_category' category.pk %}" id="delete-confirm-form">
                            {% csrf_token %}
                            <button name="single-delete" type="submit" class="btn btn-primary">Delete</button>

                            <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    {% endfor %}
</div>

Also, this is not required, but depending on the amount of categories shown, you could try to reduce the size of your HTML by adding only one modal with one form, and setting the category ID of that form when you click the Delete button.

Check out this question to see how you could pass data to a modal.

UPDATE:

The ids of all modals are identical. Change <div class="modal" id="delete-modal">

to

<div class="modal" id="delete-modal-{{category.pk}}">

and

<a type="button" data-toggle="modal" data-target="#delete-modal">Delete</a>

to

<a type="button" data-toggle="modal" data-target="#delete-modal-{{category.pk}}">Delete</a>

Nico Griffioen
  • 5,143
  • 2
  • 27
  • 36