[Django]-405 "Method POST is not allowed" in Django REST framework

4๐Ÿ‘

Make sure that you have โ€œPOSTโ€ in http_method_names. Alternatively, you can write it like this:

def allowed_methods(self):
    """
    Return the list of allowed HTTP methods, uppercased.
    """
    self.http_method_names.append("post")
    return [method.upper() for method in self.http_method_names
            if hasattr(self, method)]
๐Ÿ‘คM.Void

2๐Ÿ‘

class ApiIndexView(APIView) 

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

class ApiIndexView(generics.ListCreateAPIView) 

There are many generic views. ListCreateAPIView is used for GET and POST and CreateAPIView is used only for POST methods

๐Ÿ‘คPrasad Giri

2๐Ÿ‘

Is allways better not using empty spaces in url names.

So, instead of this:

router.register(r'', views.SomeViewSet, basename='index')

Do this:

router.register(r'some-url-name', views.SomeViewSet, basename='index')
๐Ÿ‘คKurt Brown

1๐Ÿ‘

You need to change just:

# views.py
class ApiIndexView(UpdateView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        return Response("ok")
๐Ÿ‘คSuReSh

1๐Ÿ‘

Your own comment is right. You just included the index url before. And that main view recieve url parameter for retreiving objects, so your new view is interpreted as param.
I had the same problem in urls.py:

router = DefaultRouter()
router.register(r'', views.MainViewSet, basename='index')
router.register(r'other_view', views.OtherViewSet, basename='typeservice')

Solution:

router = DefaultRouter()
router.register(r'main', views.MainViewSet, basename='index')
router.register(r'other_view', views.OtherViewSet, basename='other_view')
๐Ÿ‘คSanti Rodriguez

0๐Ÿ‘

Had the exact issue too, solved it like this.

My previous code

urlpatterns = [
    path('', views.CurriculumList.as_view(), name='list-curriculum'),
    path(
        '<slug:slug>/', views.SingleCurriculum.as_view(),
        name='get-curriculum'),
    path(
        'enroll/', views.EnrollCurriculum.as_view(),
        name='enroll-curriculum'),
]

The problem here was that when i visit url enroll/ django maps the request to the first match, which is <slug:slug>/. All i had to do was change the order, so that the actual Enroll views takes precedence.

New code

urlpatterns = [
    path('', views.CurriculumList.as_view(), name='list-curriculum'),
    path(
        'enroll/', views.EnrollCurriculum.as_view(),
        name='enroll-curriculum'),
    path(
        '<slug:slug>/', views.SingleCurriculum.as_view(),
        name='get-curriculum'),
]
๐Ÿ‘คNetrobeWebby

Leave a comment