【问题标题】:Django Rest Framework, add object to request.data and then call serializer is_valid()Django Rest Framework,将对象添加到 request.data 然后调用序列化器 is_valid()
【发布时间】:2017-05-09 13:41:18
【问题描述】:

我想知道解决这个问题的最佳方法是什么,我有一个这样的嵌套序列化程序:

serializers.py:

class PaymentMethodSerializer(serializers.ModelSerializer):

    data = serializers.JSONField()
    payment_type = PaymentTypeSerializer(required=False)

然后,视图看起来像这样:

class PaymentMethodView(APIView):
    def put(self, request, id):

        try:
            payment_method = PaymentMethod.objects.get(id=id)
        except ObjectDoesNotExist:
            return Response("No PaymentMethod with that id", status=status.HTTP_404_NOT_FOUND)

        payment_method_serialized = PaymentMethodSerializer(instance=payment_method, data=request.data)
        payment_type = request.data.get("payment_type", None)

        if payment_type:
            try:
                payment_method_type = PaymentType.objects.get(id=payment_type)
            except ObjectDoesNotExist:
                payment_method_type = None
        else:
            payment_method_type = None

    # Now, call is_valid()
        if payment_method_serialized.is_valid():
            payment_method_serialized.save(payment_type=payment_method_type)
            return Response(payment_method_serialized.data, status=status.HTTP_200_OK)

is_valid() 返回 False 并且此错误:

{"payment_type":{"non_field_errors":["Invalid data. Expected a dictionary, but got int."]}}

我明白了,我给序列化器一个pk。但是我不想创建一个带有PrimaryKeyRelatedField 的新序列化程序,而不是仅仅为此创建一个嵌套关系。如何获得与 pk 对应的 PaymentType,然后将该对象添加到 request.data 字典中,以便 is_valid 不会失败?这是解决这个问题的最佳方法吗?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    假设payment_typePaymentMethod 模型中的ForeignKey 字段,null=True 因为required=False
    如果您只提供pk,因此您不需要序列化器字段,您可以像所有其他字段一样写入fields

    class PaymentMethodSerializer(serializers.ModelSerializer):
    
        data = serializers.JSONField()
    
        class Meta:
            model = PaymentMethod
            fields = ('data', 'payment_type')
    

    它将接受pkNone。如果您想为您的 PaymentType 模型提供特殊的表示,您可以覆盖 to_representation() 方法。

    class PaymentMethodSerializer(serializers.ModelSerializer):
    
        ...
        def to_representation(self, instance):
            representation = super(PaymentMethodSerializer, self).to_representation(instance)
            representation['payment_type'] = PaymentTypeSerializer(instance.payment_type).data
            return representation
    

    现在它将使用 PaymentTypeSerializer 来表示相关的 PaymentType 模型。
    不过,您可以将 payment_type 验证移动到 serializer 中。覆盖to_internal_value,检查提供的PaymentType pk,如果错误则抛出异常,然后在视图中捕获该异常。

    【讨论】:

    • 谢谢伊万。即使我没有遵循这个解决方案。我确实发现最后一段非常有帮助:“您可以在序列化程序中移动您的 payment_type 验证。覆盖 to_internal_value,检查提供的 PaymentType pk 并在错误时抛出异常,然后在视图中捕获该异常。”这就是我接受这个答案的原因。
    猜你喜欢
    • 1970-01-01
    • 2015-09-25
    • 2017-07-12
    • 1970-01-01
    • 2014-07-07
    • 2016-09-06
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    相关资源
    最近更新 更多