2

In Django 3.1, the typical DeleteView accepts GET and POST.

See https://docs.djangoproject.com/en/3.1/ref/class-based-views/generic-editing/#deleteview

and I reproduce below:

A view that displays a confirmation page and deletes an existing object. The given object will only be deleted if the request method is POST. If this view is fetched via GET, it will display a confirmation page that should contain a form that POSTs to the same URL.

How do I do a DELETEView that's class based view and also accepts DELETE method?

Kim Stacks
  • 10,202
  • 35
  • 151
  • 282

1 Answers1

1

Tldr; I chose to use 303 at the server side so that it can correct redirect to the list view

Long story short is here https://stackoverflow.com/a/24375475/80353

In this SO answer which applies to Spring (a Java Framework), the question had the same issue as me.

  1. Send a DELETE
  2. then server side want to redirect using 302
  3. 302 will use precedent method and list typically don't accept DELETE as precedent method. Only POST, GET, and HEAD as precedent method

This seems like a web framework issue. But it's not. It appears to a convention most sensible web frameworks adopt.

There are 3 solutions with drawbacks:

1. override the convention

Allow the backend web framework to accept DELETE as precedent method for 302.

Con: Not nice by convention

2. Let client handle redirection

send back a 200 then client will redirect back to list view

Con: This results in two requests and htmx-delete doesn't work that way. It will send a DELETE method request and then take whatever comes back and immediately swap. I like this so I want to keep this. One request to settle this rather than two.

3. Use 303 for the redirection

After successful delete, do a 303 redirect to list view (I chose this)

Con: 303 doesn't work with HTTP/1.0 and older browsers. But that's not a problem in the year 2021 and will continue to be less of a problem going forward.

In the end I wrote my own deleteview

from django.views.generic.detail import BaseDetailView

class DeleteThingView(BaseDetailView):
    http_method_names = ["delete"]
    model = Thing

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        response = redirect(reverse_lazy("things-list"))
        response.status_code = 303
        return response
Kim Stacks
  • 10,202
  • 35
  • 151
  • 282