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

Django 如何更新单行上的单个列?,django,django-rest-framework,Django,Django Rest Framework,我正试图为我的Django REST应用程序编写一个简单的更新视图,但我不知道怎么做。我得到了从403到500的误差范围 基本上,我有一个表'Foo',我想将'active'字段从'True'设置为'False'。以下是我目前的观点: class DisableFoo(generics.UpdateAPIView): permission_classes = (permissions.IsAuthenticated,) serializer_class = FooSerializ

我正试图为我的Django REST应用程序编写一个简单的更新视图,但我不知道怎么做。我得到了从403到500的误差范围

基本上,我有一个表'Foo',我想将'active'字段从'True'设置为'False'。以下是我目前的观点:

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)
但是,这会导致断言错误:

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.

您不应发送要使用request.data更新的行的
id
,而应在
url
中发送

因此,如果你现在正在击球,比如:

/api/foo/

试一试

/api/foo/

当然,这还不够。你还应该考虑更多的事情。

您正在挂接
perform\u update
方法。但这不太可能是正确的<调用code>perform\u update是为了用
serializer.save()
更新整个对象,因此只有当
serializer.is\u valid()
时才会调用它

这意味着您必须发送有效的
Foo
对象。但那不是你想要的。您只需要更新
Foo
对象的单个字段。因此,正确的方法是使用
partial\u update
<当您请求
/api/foo/

因此,如果您在请求中向
/api/foo/
发送
补丁
请求,且
active=0
,则数据DRF将自动更新对象,而无需任何进一步的代码更改。只是使用

class DisableFoo(generics.UpdateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = FooSerializer
    queryset = Foo.objects.all()
但这最终将公开所有要更新的模型字段。因此,您可以覆盖
partial\u update
方法,如下所示:

def partial_update(self, request, *args, **kwargs):
    instance = self.get_object()
    instance.active = False
    instance.save(update_fields=['active'])
    return Response()
另一种方法 DRF支持创建via
@detail\u route
@list\u route
装饰器

您可以使用
@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')
/api/foo//disable
发出
POST
请求将调用我们刚刚编写的
disable
方法,并禁用
下的
foo
实例


通过这种方式,您可以避免使用
PATCH
request方法的要求。

我更改了它,但现在得到了HTTP 400错误请求作为答复。我用一些解释更新了答案,但您还应该通过查看错误日志来了解如何调试此类错误。谢谢,我将在一分钟内尝试更改。同时,如果请求总是将值设置为False,我是否必须在请求中设置
active=0
?这不是多余的吗?另外,我的HTTP客户端不支持补丁方法。如果不覆盖
partial\u update
,则必须在请求中发送它。这基本上告诉序列化程序使用什么值更新哪个字段。因此,如果您还发送
active=0&some\u other\u field=some\u other\u value
,它们都将得到更新。关于不受支持的
补丁
方法,请检查我的更新答案。