Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django REST Framework - 405 METHOD NOT ALLOWED using SimpleRouter

Tags:

I'm using the SimpleRouter tuorial within the docs.

Just to test I've created a temporary Authentication class:

class BackboneBasicAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        user = User.objects.filter(username="james")
        return (user, None)

settings look like this

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'core.rest_authentication.BackboneBasicAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
       'rest_framework.permissions.AllowAny',
    ),
}

Submitting a PUT request returns a 405 METHOD NOT ALLOWED

{"detail": "Method 'PUT' not allowed."}

I've tried with X-HTTP-Method-Override as well. No go.

Any ideas what I'm doing wrong?

I've spent a whole day trying to figure this out, hopefully someone can help! :)

like image 254
RadiantHex Avatar asked Jun 17 '13 15:06

RadiantHex


People also ask

How do I return 405 in Django?

If you want to return a custom one just do the following: return render(request, "Error Pages/405. html", status=405) . Notice the status, that is what will tell the browser about the code that is being returned.

What is permission in Django REST framework?

Permissions are used to grant or deny access for different classes of users to different parts of the API. The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds to the IsAuthenticated class in REST framework.


2 Answers

The simple router adds the put attribute to the view for a url matching the pattern you supply with the pk added as an additional pattern element.

For example if you used:

simple_router.register('widgets/', WidgetViewSet)

The framework will create two url patterns:

'^widgets/$'
'^widgets/<?P<pk>[^/]+/$'

I am guessing that you are only trying urls that satisfy the first match for which the viewset instance will only have 'get' ('list') and 'post' ('create') support added by the framework so it will cause the error you are seeing if you try to put/patch or delete. For those methods to work you need to supply the pk so that the framework knows which widget you are modifying or deleting and so that your url matches the view that supports those methods.

This is confusing and you may choose not to use the simple_router at all if you find it too confusing. Then you can specify your own method mapping so that the rest_framework will dispatch to your put methods e.g.

url('^widgets/<?P<pk>[^/]+/$', WidgetViewSet.as_view({'put': 'update', 
                                                      'get': 'retrieve', 
                                                      'patch': 'partial_update', 
                                                      'delete': 'destroy'}...)
like image 196
Paul Whipp Avatar answered Jan 15 '23 18:01

Paul Whipp


To me that seems to be caused by the routed viewset not implementing or not allowing PUT requests. If it was an authentication issue, you would get a 401 UNAUTHORIZED status code.

like image 43
Lukas Bünger Avatar answered Jan 15 '23 19:01

Lukas Bünger