ensarman
ensarman

Reputation: 310

Django DeleteView without slug and via POST

Hello I want to delete an object in a model but I don't want to show the id in the slug, so I realized I can send the data via a hidden tag in a form, but I didn't manage to make it work

Template

<form action="{% url "delete_url" %}" method="post">
    {% csrf_token %}
    <input type="hidden" name="pk" value={{ model.pk }}>
    <button type="submit">Delete</button>
</form>

Url. Check I don't want slug

path("delete_view", views.MyDeleteView.as_view(), name="delete_url")

View

class MyDeleteView(DeleteView):
    model=ModelName
    success_url = reverse_lazy("success_url")

Upvotes: 0

Views: 1093

Answers (2)

Serafeim
Serafeim

Reputation: 15104

First of all, your sample code has various problems which need to be fixed:

  1. The input type should be hidden, not hiden.
  2. Your class based view name should have proper capitalization: MyDeleteView, not delete_view

Now, for your actual problem: The DeleteView uses SingleObjectMixin to identify the object (check this out https://ccbv.co.uk/projects/Django/2.0/django.views.generic.edit/DeleteView/). Thus, you need to override the get_object method of SingleObjectMixin so as to use the POST data instead of the slug to retrieve the object. Probably something like this should work (warning there's no error handling):

  class MyDeleteView(DeleteView):
    model=ModelName
    success_url = reverse_lazy("success_url")

    def get_object(self, queryset=None):
      pk = self.request.POST['pk']
      return self.get_queryset().filter(pk=pk).get()

For a gentle introduction to CBV I recommend my CBV guide: https://spapas.github.io/2018/03/19/comprehensive-django-cbv-guide/

Upvotes: 1

ensarman
ensarman

Reputation: 310

Thanks to Serafeim I can find the way to do it, I have to replace the get_object() method and copy some code from the original method. I get the code from the link: https://ccbv.co.uk/projects/Django/2.0/django.views.generic.edit/DeleteView/

Finaly:

class MyDeleteView(DeleteView):
    model=ModelName
    success_url = reverse_lazy("success_url")

def get_object(self, queryset=None):
    pk = self.request.POST['pk']
    if queryset is None:
        queryset = self.get_queryset()
    if pk is not None:
        queryset = queryset.filter(pk=pk)
    try:
        # Get the single item from the filtered queryset
        obj = queryset.get()
    except queryset.model.DoesNotExist:
        raise Http404("No %(verbose_name)s found matching the query" %
                      {'verbose_name': queryset.model._meta.verbose_name})

    return obj

Upvotes: 0

Related Questions