405“Method POST is not allowed”在Django REST框架中

mrzz3bfm  于 2023-05-01  发布在  Go
关注(0)|答案(6)|浏览(183)

我是Django REST框架的新手。有人能解释为什么我得到这样的错误,如果我做一个POST请求'/API/index/'

405 Method Not Allowed
{"detail":"Method \"POST\" not allowed."}

我的代码如下:

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

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

# urls.py
urlpatterns = [
    url(r'^api/index/$', views.ApiIndexView.as_view()),
]

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.DjangoModelPermissions',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    )
}

但是如果我把<pk>添加到我的模式中,一切都正常:

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

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

# urls.py
urlpatterns = [
    url(r'^api/index/(?P<pk>\d+)/$', views.ApiIndexView.as_view()),
]

我完全糊涂了。为什么必须使用<pk>,有没有方法避免在URL模式中使用这个参数?

6gpjuf90

6gpjuf901#

确保http_method_names中有**“POST”**。或者,你可以这样写:

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

xggvc2p62#

最好不要在网址名称中使用空格。
所以,与此相反:

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

这样做:

router.register(r'some-url-name', views.SomeViewSet, basename='index')
niwlg2el

niwlg2el3#

你只需要改变:

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

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

brccelvz4#

class ApiIndexView(APIView)

请将import from rest_framework import generics改为

class ApiIndexView(generics.ListCreateAPIView)

有许多通用的观点。ListCreateAPIView用于GET和POST,CreateAPIView仅用于POST方法

lvjbypge

lvjbypge5#

你自己的评论是对的。您之前只包含了索引url。且主视图接收用于检索对象URL参数,因此您的新视图被解释为参数。我在URLs中遇到了同样的问题。py

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

解决方案:

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

6fe3ivhb6#

也有问题,就这样解决了。
我以前的代码

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

这里的问题是,当我访问url enroll/时,django将请求Map到第一个匹配项,即<slug:slug>/。我所要做的就是更改顺序,以便实际的Enroll视图优先。
新代码

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

相关问题