首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在没有/<id>的请求中不允许方法PUT

在没有/<id>的请求中不允许方法PUT
EN

Stack Overflow用户
提问于 2019-06-03 01:01:09
回答 2查看 3.3K关注 0票数 2

我有一个简单的ModelViewSet

代码语言:javascript
复制
class PersonViewSet(viewsets.ModelViewSet):
  queryset = Person.objects.all().order_by('id')
  serializer_class = PersonSerializer

并使用urls.py

代码语言:javascript
复制
router = routers.DefaultRouter()
router.register(r'persons', views.PersonViewSet)

我需要请求一个PUT

/persons

带着身体

代码语言:javascript
复制
{
  "id":10,
  "login":"alfredo",
  "avatar_url":"https://avatars.com/2222"
}

来更新avatar_url。但是,当使用此url '/persons‘调用带有方法的PUT时,我会得到响应代码405

代码语言:javascript
复制
{
  "detail": "Method \"PUT\" not allowed."
}

(我知道更好的方法是调用'/persons/10',但项目的要求是将'/persons‘和id放在主体请求中)

如何实现此终结点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-03 01:13:23

PUT方法没有在ModelViewSet类上实现,您可以在这里查看:http://www.cdrf.co/3.9/rest_framework.viewsets/ModelViewSet.html这是一个很好的文档,介绍了默认情况下实现的方法。

要使您的PUT方法工作,您应该添加以下代码:

代码语言:javascript
复制
def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

编辑:考虑到url是:/persons/<id>

票数 3
EN

Stack Overflow用户

发布于 2019-06-04 09:56:57

您会收到此错误,因为URL /person/不应用于PUT请求。PUT请求与视图集update方法相对应,update方法需要URL中的ID,例如/person/10/,以便检索要更新的Person对象。

实际解决此问题的方法是扩展DefaultRouter类,为list端点上的PUT添加另一个操作,并自定义视图get_object方法以从有效负载检索ID。

SimpleRouter类中,您将看到定义如下的路由:

代码语言:javascript
复制
routes = [
    # List route.
    Route(
        url=r'^{prefix}{trailing_slash}$',
        mapping={
            'get': 'list',
            'post': 'create',
            'put': 'update'  # Add this entry to the mapping dictionary
        },
        name='{basename}-list',
        detail=False,
        initkwargs={'suffix': 'List'}
    ),
    # Dynamically generated list routes. Generated using
    # @action(detail=False) decorator on methods of the viewset.
    DynamicRoute(
        url=r'^{prefix}/{url_path}{trailing_slash}$',
        name='{basename}-{url_name}',
        detail=False,
        initkwargs={}
    ),
    # Detail route.
    Route(
        url=r'^{prefix}/{lookup}{trailing_slash}$',
        mapping={
            'get': 'retrieve',
            'put': 'update',
            'patch': 'partial_update',
            'delete': 'destroy'
        },
        name='{basename}-detail',
        detail=True,
        initkwargs={'suffix': 'Instance'}
    ),
    # Dynamically generated detail routes. Generated using
    # @action(detail=True) decorator on methods of the viewset.
    DynamicRoute(
        url=r'^{prefix}/{lookup}/{url_path}{trailing_slash}$',
        name='{basename}-{url_name}',
        detail=True,
        initkwargs={}
    ),
]

您需要将{'put': 'update'}添加到# List route.部分,然后定制视图集的updateget_object方法,以便它从有效负载中检索ID。我将提供一个自定义get_object方法的示例来支持此用例:

代码语言:javascript
复制
def get_object(self):
    if self.action == "update" and self.kwargs.get(self.lookup_url_kwarg) is None:  # Check if this is an update method to the list view, the URL kwargs for the lookup will not be populated
        person_id = self.request.data.get("id")
        return Person.objects.get(pk=person_id)
    return super().get_object()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56417126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档