我试图为我的Django REST应用程序编写一个简单的更新视图,但我无法弄清楚如何做到这一点。我收到了403到500之间的一系列错误。
基本上,我有一张桌子' Foo'我想设置“活跃的'来自' True'错误'。以下是我目前的观点:
class DisableFoo(generics.UpdateAPIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = FooSerializer
queryset = Foo.objects.all()
def perform_update(self, serializer):
queryset = Foo.objects.filter(pk = self.request.data['id'])
queryset.update(active = False)
但是,这会导致AssertionError:
Expected view DisableFoo to be called with a URL keyword argument named "pk".
Fix your URL conf, or set the '.lookup_field' attribute on the view correctly.
答案 0 :(得分:1)
您不应使用request.data在id
内发送要更新的行的url
。
所以如果你现在正在点击:
/api/foo/
尝试
/api/foo/<id>/
当然这还不够。你还应该考虑更多的事情。
您正在使用perform_update
方法。但这不太可能是正确的。调用perform_update
是为了使用serializer.save()
更新整个对象,因此仅在serializer.is_valid()
时才会调用它。
这意味着您必须发送有效的Foo
对象。但那不是你想要的。您只需要更新Foo
对象的单个字段。所以这里正确的方法是使用partial_update
。当您向partial_update
PATCH
请求时,将使用/api/foo/<id>/
因此,如果您向PATCH
发送/api/foo/<id>/
请求,其中active=0
在request.data内,DRF将自动更新对象,而无需进一步更改代码。只是使用
class DisableFoo(generics.UpdateAPIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = FooSerializer
queryset = Foo.objects.all()
但这最终会使您的所有模型字段公开以进行更新。所以你可以像这样覆盖partial_update
方法:
def partial_update(self, request, *args, **kwargs):
instance = self.get_object()
instance.active = False
instance.save(update_fields=['active'])
return Response()
DRF支持通过@detail_route
和@list_route
装饰器创建extra extra-actions。
您可以使用@detail_route
创建自定义禁用操作。考虑以下代码的和平:
class FooViewSet(viewsets.GenericViewSet):
queryset = Foo.objects.all()
serializer_class = FooSerializer
@detail_route(methods=['post'])
def disable(self, request, pk=None):
instance = self.get_object()
instance.active = False
instance.save(update_fields=['active'])
return Response('done')
向POST
发出/api/foo/<id>/disable
请求会调用我们刚刚编写的disable
方法,并在foo
下禁用<id>
个实例。
这样您就可以逃避使用PATCH
请求方法的要求。