[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)]

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

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')

1๐Ÿ‘

You need to change just:

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

    def post(self, request, format=None):
        return Response("ok")

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')

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'),
]

Leave a comment