当Django REST Framework中不存在UpdateAPIView时不引发404

时间:2019-06-06 06:06:37

标签: django django-rest-framework

我正在使用 Django 2.2 Django REST Framework

我有一个端点来更新现有记录,扩展了 UpdateAPIView

class FakeOrderPaymentView(generics.UpdateAPIView):
    serializer_class = OrderPaymentSerializer
    permission_classes = (IsAuthenticated,)

    def get_object(self):
        log.debug(self.request.data)
        order_id = self.request.data.get('order_id', None)
        if not order_id:
            raise Http404

        return self.serializer_class.Meta.model.objects.filter(pk=order_id).first()

    def perform_update(self, serializer):
        return serializer.save()

    def update(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        instance = self.perform_update(serializer)
        instance_serializer = OrderListSerializer(instance)
        return Response(instance_serializer.data)

OrderPaymentSerializer

class OrderPaymentSerializer(serializers.ModelSerializer):
    order_id = serializers.IntegerField(write_only=True, required=False)
    order_status = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = Order
        fields = [
            'order_status',
            'order_id'
        ]

    def create(self, validated_data):
        log.debug(validated_data)
        return super().create(validated_data)

    def update(self, instance, validated_data):
        status = validated_data.pop('order_status', None)
        order_id = validated_data.pop('order_id', None)
        instance.status = Order.STATUS.COMPLETED
        return super().update(instance, validated_data)

order_id order_status 不是模型字段。他们只是为了携带数据。

如果order_id不在PUT数据中,或者order_id为空白。它应该会引发404响应。

但是,它不是在get_object()之前调用update()方法。 同样,即使我在PUT数据中传递了order_idperform_update()方法正在调用序列化程序的create()方法,而不是update()方法。

  1. 何时调用序列化程序的update()方法?
  2. 为什么get_object()没有自动呼叫?

1 个答案:

答案 0 :(得分:0)

  
      
  1. 何时调用序列化程序的update()方法?
  2.   

documentation指出:

  

调用.save()将创建一个新实例,或更新一个现有实例,具体取决于在实例化序列化程序类时是否传递了一个现有实例

由于在实例化序列化程序时未提供实例,因此调用save将转换为create而不是update

  
      
  1. 为什么get_object()没有自动调用?
  2.   

因为您查看的update方法已被覆盖,而您没有调用get_object。默认DRF update为:

def update(self, request, *args, **kwargs):
    partial = kwargs.pop('partial', False)
    instance = self.get_object()
    serializer = self.get_serializer(instance, data=request.data, partial=partial)
    serializer.is_valid(raise_exception=True)
    self.perform_update(serializer)

    if getattr(instance, '_prefetched_objects_cache', None):
        # If 'prefetch_related' has been applied to a queryset, we need to
        # forcibly invalidate the prefetch cache on the instance.
        instance._prefetched_objects_cache = {}

    return Response(serializer.data)