【问题标题】:Django rest framework writeable nested serializer data missing from validated_data验证数据中缺少 Django REST 框架可写嵌套序列化程序数据
【发布时间】:2018-09-04 23:58:29
【问题描述】:

我正在尝试为我的 API 端点创建一个可写的嵌套序列化程序,但是在输入我的父序列化程序的 create 方法后,嵌套数据不会出现在我的 validated_data 字典中,就像它应该在示例中一样 @ 987654321@。相反,嵌套键甚至不存在于字典中。相反,它看起来像:{'foo': 'bar'}。因此,嵌套键似乎被展平,具有相同键的任何其他嵌套对象都将被覆盖。

关于问题可能是什么的任何线索?我有一些相当复杂的验证逻辑,但是在删除所有这些之后,问题没有得到解决,所以它似乎无关紧要。

我的模型是这样定义的:

class Payment(models.Model):
    id = models.AutoField(primary_key=True)
    foo = models.CharField(max_length=15, blank=True, null=True)

class Booking(models.Model):
    id = models.AutoField(primary_key=True)
    payment = models.ForeignKey(Payment, blank=True, null=True)

我的序列化器:

class PaymentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        fields = '__all__'

class BookingSerializer(serializers.ModelSerializer):
    payment = PaymentSerializer(source='*', write_only=True)

    def create(self, validated_data):
        print("Creating booking", validated_data) # Outputs "Creating booking {'foo': 'bar'}"
        payment_data = validated_data.pop('payment') # Obviously errors at this point
        primary_guest = Payment.objects.create(payment_data)
        booking = Booking.objects.create(**validated_data)
        # other creation related code

        return booking

    class Meta:
        fields = '__all__'

我的视图集:

class PrebookingViewSet(viewsets.ModelViewSet):
    queryset = Booking.objects.all().order_by('id')
    serializer_class = BookingSerializer

我的请求包含以下 POST 正文:

{
    "payment": {
        "foo": "bar"
    }
}

【问题讨论】:

  • 你在这里期待什么 - 支付下的许多 foos?
  • 不,我希望validated_data 字典与文档示例一样嵌套,链接。很像请求正文。我的例子是高度简化的。

标签: python django django-rest-framework


【解决方案1】:

问题是您已将其定义为 source='*',

来自DRF Serializer Doc

source='*'这个值有特殊的含义,用来表示应该将整个对象传递给字段。这对于创建嵌套表示或需要访问完整对象以确定输出表示的字段很有用

也就是说,您的有效载荷 {"payment": {"foo": "bar"}} 将进入 PaymentSerializer 而不是 {"foo": "bar"}


解决方案
只需删除 source='*' ;)

class BookingSerializer(serializers.ModelSerializer):
    payment = PaymentSerializer(write_only=True)

    def create(self, validated_data):
        # your code

【讨论】:

  • 对了,谢谢,我自己解决了。关于为什么它对顶级序列化程序中的验证数据有这种影响的任何提示?看起来不太直观。
  • 我认为我提供的链接是不言自明的,不是吗?
【解决方案2】:

在我完成所有故障排除之后,我或多或少地偶然发现了问题的解决方案,同时提出了一个示例来分享我的问题。这是一个很好的锻炼。问题是由我的嵌套序列化器字段定义引起的。

代替:

payment = PaymentSerializer(source='*', write_only=True)

我需要:

payment = PaymentSerializer(write_only=True)

我的validated_data 字典现在在付款键下包含一个嵌套字典。

我不确定我为什么要包含它,我想我已经在其他地方使用它来将字段展开为嵌套表示。我似乎找不到任何关于它应该如何工作的文档,以及它为什么会导致我在这里看到的行为。欢迎对此提出任何意见!

【讨论】:

    猜你喜欢
    • 2018-07-07
    • 1970-01-01
    • 2021-09-22
    • 2019-12-23
    • 2019-10-13
    • 2018-07-06
    • 1970-01-01
    • 2021-06-23
    • 2016-05-14
    相关资源
    最近更新 更多