46

I'm trying to develop a REST provider with OAuth. I'm using Django RESTFramework and DjangoOAuthToolkit. I did a GET and it works perfectly but I'm trying to use a POST and the server responds with {"detail": "Method 'POST' not allowed."} This is my code:

# views.py
@api_view(['POST'])
def pruebapost(request):
    usuario = User()
    access_token = Token.objects.get(
        key=request.POST['oauth_token']
    )
    usuario = access_token.user
    content = {'saludo': usuario.username}
    return Response(content)

# settings.py
OAUTH_AUTHORIZE_VIEW = 'principal.views.oauth_authorize'
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer'
REST_FRAMEWORK = {
   'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
   'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    ),
   'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.OAuthAuthentication',
    ),
}

And I'm using this as a "test" client:

import urlparse
import oauth2 as oauth
import requests

consumer_key = "clave"
consumer_secret = "secreto"
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
resource_url = 'http://blablabla.pythonanywhere.com/prueba'
consumer = oauth.Consumer(key='clave', secret='secreto')
token = oauth.Token(key='e7456187a43141af8d2e0d8fa99b95b9',
                    secret='3wRIKoacff16tcew')

oauth_request = oauth.Request.from_consumer_and_token(
    consumer,
    token,
    http_method='POST',
    http_url=resource_url,
    parameters={'hola':'pepe'}
)
oauth_request.sign_request(
    oauth.SignatureMethod_HMAC_SHA1(),
    consumer,
    token
)
url = oauth_request.to_url()
response = requests.post(url, oauth_request.to_postdata())
print response.content

I don't understand what REST Framework documentation says about 405 Method not allowed

"Raised when an incoming request occurs that does not map to a handler method on the view."

Thanks

Ania Warzecha
  • 1,770
  • 13
  • 25
ecorzo
  • 515
  • 1
  • 5
  • 7
  • 2
    Basically that error means that you haven't allowed specific HTTP method to be called on a specific view, or, more often that you are calling a wrong url. Check if you are calling the proper one. You can also provide your urls config here. – Ania Warzecha Apr 10 '14 at 18:41
  • 4
    Problem solved, I miss one slash on the url. Very nooby issue. Thanks! – ecorzo Apr 11 '14 at 15:18
  • 1
    possible duplicate of [Django/DRF - 405 Method not allowed on DELETE operation](http://stackoverflow.com/questions/26711975/django-drf-405-method-not-allowed-on-delete-operation) – Kevin Brown Jul 20 '15 at 23:35
  • In my case the endpoint wasn't even available. I forgot to add it to the urls.py. Very confusing. – elena Oct 02 '18 at 02:31

4 Answers4

57

This was resolved in the comments by user2663554

Problem solved, I miss one slash on the url.

This response code (405) can come from any number of issues, but it generally ends up that either you are using the wrong URL (as in this case), or you are using the wrong request method. Sometimes it's both!

Quite often I see people getting this issue when they are trying to update an individual resource (/api/res/1), but they are using the list url (/api/res) which doesn't allow the request to be made. This can also happen in the reverse, where someone is trying to create a new instance, but they are sending a POST request to the individual object.

In some cases, the wrong url is being used, so users are requesting a standard non-API view and thinking it is an API view (/res instead of /api/res). So make sure to always check your urls!

Community
  • 1
  • 1
Kevin Brown
  • 36,829
  • 37
  • 188
  • 225
15

In my case i had a router with same base url

router.register('sales', SalesViewSet, basename='sales')

and my url patterns was

urlpatterns = [
    path('', include((router.urls, app_name))),
    path('sales/analytics/', Analytics.as_view(), name='create'),
]

I was getting 405 error for sales/analytics/. The solution was change the order of urlpatterns.

urlpatterns = [
    path('sales/analytics/', Analytics.as_view(), name='create'),
    path('', include((router.urls, app_name))),
]
Nithin
  • 3,969
  • 25
  • 37
3
class ApiIndexView(APIView)

instead of this please "import from rest_framework import generics" and change it to

class ApiIndexView(generics.ListCreateAPIView) 

there are many views in generic listcreateAPIview is used for get and post and createapiview is used only for post methods

Prasad Giri
  • 108
  • 7
1

My first answer on SO. After trying everything here and being frustrated for the past 6 hours, it finally hit me and I found another reason this might be happening; I, quite simply, was not logged in to /admin. I logged in to /admin and that fixed the "HTTP 405 method not allowed" problem i.e. the post view not coming up. I hope this helps anyone stuck with this kind of issue.

ce0la
  • 73
  • 1
  • 4