我有一个简单的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
/人
随身
{
"id":10,
"login":"alfredo",
"avatar_url":"https://avatars.com/2222"
}
更新avatar_url。但是,当使用方法PUT用此URL'/ persons'进行调用时,我得到响应代码405
{
"detail": "Method \"PUT\" not allowed."
}
(我知道这样做的更好方法是调用'/ persons / 10',但是该项目的要求是将PUT'/ persons'的ID放在主体请求中)
如何实现此端点?
答案 0 :(得分:3)
尚未在ModelViewSet类上实现PUT方法,您可以在此处进行检查:http://www.cdrf.co/3.9/rest_framework.viewsets/ModelViewSet.html它是有关默认情况下实现了哪些方法的不错的文档。
要使您的PUT方法起作用,您应该添加以下代码:
d = {j:i for i, j in enumerate(List1)}
# {'Z': 0, 'Q': 1, 'X': 2, 'J': 3, 'K': 4, ...
''.join(sorted(List2, key = lambda x: d[x]))
# 'VRATE'
编辑:考虑到该URL为:def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
答案 1 :(得分:0)
您收到此错误,因为URL /person/
不能与PUT
请求一起使用。 PUT
个请求对应于视图集update
方法,而update
方法要求URL中有一个ID,例如/person/10/
,以便检索Person
对象以进行更新。
实际解决此问题的方法是扩展DefaultRouter
类以在列表端点上为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()