我正在尝试为我的API端点创建一个可写的嵌套序列化程序,但是在输入父序列化程序的create
方法后,嵌套数据不会像应该那样出现在我的validated_data
字典中在示例here中。而是,嵌套键甚至不在字典中。相反,它看起来像:{'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__'
我的ViewSet:
class PrebookingViewSet(viewsets.ModelViewSet):
queryset = Booking.objects.all().order_by('id')
serializer_class = BookingSerializer
我的请求包含以下POST正文:
{
"payment": {
"foo": "bar"
}
}
答案 0 :(得分: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
答案 1 :(得分:0)
在完成所有故障排除后,它似乎或多或少地偶然发现了该问题的解决方案,同时提出了一个示例来分享我的问题。这是一个很好的锻炼。问题是由我嵌套的序列化程序字段定义引起的。
代替:
payment = PaymentSerializer(source='*', write_only=True)
我需要:
payment = PaymentSerializer(write_only=True)
我的validated_data
词典现在在付款键下包含一个嵌套的词典。
我不确定为什么要包括在内,我想我已在其他地方使用它来将字段平展为嵌套表示形式。我似乎找不到关于它如何工作以及为什么导致我在这里看到的行为的任何文档。欢迎对此提供任何输入!