PATCH 请求到 Django Rest 框架中的 ModelViewSet - 如何实现 serializer.update()?

Esc*_*her 4 python django django-rest-framework

我正在尝试使用我的产品 API来实现PATCH处理。ModelViewSet(Product 实例主键是 a uuid,因此在下面的代码中uuid显示为)。lookup_field

我对如何重写update()ModelSerializer 类方法感到困惑。源中的存根如下所示:

def update(self, instance, validated_data):
    raise NotImplementedError('`update()` must be implemented.')
Run Code Online (Sandbox Code Playgroud)

我不明白为什么instance并且validated_data应该提供,因为它们应该是序列化器的实例化属性:( 在文档中向上get_serializer(self, instance=None, data=None, many=False, partial=False)滚动一段)。为什么我应该提供经过验证的数据?序列化器不是应该验证它吗?

这是我的partial_update()实现:

Product.py(ViewSet 类)

def get_object(self, uuid=None):
    """ Utility method to get the object """
    # authentication logic, returns None if object not found

def partial_update(self, request, uuid=None):
    instance = self.get_object(uuid)
    if not instance:
        return Response(status=status.HTTP_404_NOT_FOUND)
    serializer = self.get_serializer(instance, 
                    data=request.data,
                    many=isinstance(request.data, list),
                    partial=True)
    if not serializer.is_valid():
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    serializer.update() #NOT WORKING; NEEDS ARGS instance, validated_data
    return Response(serializer.data, status=status.HTTP_200_OK)
Run Code Online (Sandbox Code Playgroud)

序列化器.py

def update(self, instance, validated_data):
    # we link up the user foreign key here
    user=User.objects.filter(email=validated_data.pop('user', None)).first()
    if user:
        instance.fk_user = user

    #specify which fields to update, otherwise save() tries to SQL SET all fields
    update_fields = [k for k in validated_data]
    if user:
        update_fields.append('fk_user')
    for k,v in validated_data.items():
        setattr(instance, k, v)
    instance.save(update_fields=update_fields)
    return instance
Run Code Online (Sandbox Code Playgroud)

Lin*_*via 7

这是一个很好且明智的问题。

关键是,如果没有提供instancevalidated_data,我们就会有很多关于如何访问它们的问题,加上与createvs的一些混淆update(它们将具有相同的签名,为什么不只制作一个)。

但是,您应该直接调用序列化器的createor !!update

您只需要调用,它就会执行到或的serializer.save()路由createupdate

即替换:

serializer.update() #NOT WORKING; NEEDS ARGS instance, validated_data
Run Code Online (Sandbox Code Playgroud)

serializer.save()
Run Code Online (Sandbox Code Playgroud)