Skip to main content
 首页 » 编程设计

python之在 django rest 框架中对 ModelViewSet 的 PATCH 请求之我如何实现 serializer.update()

2024年08月20日31jpfss

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

我对如何覆盖 update() ModelSerializer 类方法感到困惑。源代码中的 stub 如下所示:

def update(self, instance, validated_data): 
    raise NotImplementedError('`update()` must be implemented.') 

我不明白为什么要提供 instance 和 validated_data ,因为根据实例化,它们应该是序列化程序的属性: get_serializer(self, instance=None, data=None, many=False, partial=False)(向上滚动一段 here in the documentation)。为什么我应该提供经过验证的数据?序列化程序不应该验证它吗?

这是我的 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) 

序列化器.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 

请您参考如下方法:

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

重点是,如果未提供 instance 和 validated_data,我们将有大量关于如何访问它们的问题,加上一些与 create 的混淆 vs update(它们会有相同的签名,那为什么不只做一个)。

但是,您不应该直接调用序列化程序的create 或update!!

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

即替换:

serializer.update() #NOT WORKING; NEEDS ARGS instance, validated_data 

与

serializer.save()