Home > front end >  django rest framework method 'DELETE' not allowed because DefaultRouter
django rest framework method 'DELETE' not allowed because DefaultRouter

Time:04-04

This is my first project with Django and I am having a bit of trouble with the URLs.

I have a customer model and I created the ModelViewSet for it so I can retrieve, delete and update the models in the database.

To get all the basic URLs I used rest_framework.routers.DefaultRouter and registered the CustomerViewSet to it like so:

router = routers.DefaultRouter()
router.register(r'customers', CustomerViewSet, basename='customers')

And then registered the URLs like so:

urlpatterns = [
    path('', include(router.urls), name="customers"),
]

My problem is that I need to add a new URL for deleting all the customers in the database.

I tried adding it like so:

urlpatterns = [
    path('', include(router.urls), name="customers"),
    path('customers/', deleteAllCustomers, name='deleteAll'),
]

Where deleteAllCustomers is a function decorated with api_view(['DELETE'].

When I try to call this URL (using Postman), I get 405 error (method 'DELETE' not allowed).

From what I understand, it happens because that URL is already assigned by the DefaulteRouter for PUT/POST methods.

I tried adding a destroy function to my CustomerViewSet, but it is only called when deleting one instance (with primary key passed in the URL).

I haven't found a way to make the URL work and wasn't able to find any similar question.

CodePudding user response:

Looking at your code snippet. The url path for deleteAllCustomers and CustomerViewSet are the same i.e .../customers

I think your app urls.py file should look like this:

from django.urls import path, include
from rest_framework.routers import DefaultRouter

from customers import views


router = DefaultRouter()
router.register('', views.CustomerViewSet,
                basename="customers")

app_name = 'customers'

urlpatterns = [
    path('customers/', deleteAllCustomers, name='deleteAll'),
    path('', include(router.urls)),
    
]

The order of the url patterns is important.

Your views.py file for CustomerViewSet should look like this to support: GET,CREATE,PUT,PATCH,RETRIEVE,DELETE

from rest_framework import viewsets, mixins, permissions, authentication


class CustomerViewSet(viewsets.GenericViewSet,
                       mixins.ListModelMixin,
                       mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyMixin
                       ):
    authentication_classes = (authentication.TokenAuthentication,)
    permission_classes = (permissions.IsAuthenticated)

    serializer_class = serializers.CustomerModelSerializer
    queryset = models.Customers.objects.all()

Then you can set up your deleteAllCustomers views how you want to.

CodePudding user response:

Thanks to Oluwatomisin Omotosho James for helping me with this.

I forgot to mention that in my case I need the URL /customers/ to support both the POST and DELETE methods.

So I changed the deleteAllCustomers function to also handle the POST request. (And like they suggested, reordering the urlpatterns array)

The code now works great

  • Related