我有一个简单的ModelViewSet
class PersonViewSet(viewsets.ModelViewSet):
queryset = Person.objects.all().order_by('id')
serializer_class = PersonSerializer
并使用urls.py
router = routers.DefaultRouter()
router.register(r'persons', views.PersonViewSet)
我需要请求一个PUT
/persons
带着身体
{
"id":10,
"login":"alfredo",
"avatar_url":"https://avatars.com/2222"
}
来更新avatar_url。但是,当使用此url '/persons‘调用带有方法的PUT时,我会得到响应代码405
{
"detail": "Method \"PUT\" not allowed."
}
(我知道更好的方法是调用'/persons/10',但项目的要求是将'/persons‘和id放在主体请求中)
如何实现此终结点?
发布于 2019-06-03 01:13:23
PUT方法没有在ModelViewSet类上实现,您可以在这里查看:http://www.cdrf.co/3.9/rest_framework.viewsets/ModelViewSet.html这是一个很好的文档,介绍了默认情况下实现的方法。
要使您的PUT方法工作,您应该添加以下代码:
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
编辑:考虑到url是:/persons/<id>
发布于 2019-06-04 09:56:57
您会收到此错误,因为URL /person/
不应用于PUT
请求。PUT
请求与视图集update
方法相对应,update
方法需要URL中的ID,例如/person/10/
,以便检索要更新的Person
对象。
实际解决此问题的方法是扩展DefaultRouter
类,为list端点上的PUT
添加另一个操作,并自定义视图get_object
方法以从有效负载检索ID。
在SimpleRouter
类中,您将看到定义如下的路由:
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.
部分,然后定制视图集的update
或get_object
方法,以便它从有效负载中检索ID。我将提供一个自定义get_object
方法的示例来支持此用例:
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()
https://stackoverflow.com/questions/56417126
复制相似问题