如何更新单行上的单个列?

时间:2015-04-28 04:34:56

标签: django django-rest-framework

我试图为我的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.

1 个答案:

答案 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请求方法的要求。