更新期间嵌套序列化程序的验证数据中缺少默认值

时间:2019-03-05 14:07:16

标签: python django django-rest-framework

我正在尝试在Django Rest Framework中实现update-method for nested representations

from django.db import models
from django.utils import timezone

from rest_framework import serializers


class Foo(models.Model):
    pass


class Bar(models.Model):
    foo = models.ForeignKey(Foo, on_delete=models.CASCADE, null=False, related_name='bars')
    name = models.CharField(max_length=255)
    create_date = models.DateField(null=False)


class BarSerializer(serializers.ModelSerializer):
    create_date = serializers.DateField(default=timezone.now)

    class Meta:
        model = Bar
        fields = ('name', 'create_date',)


class FooSerializer(serializers.ModelSerializer):
    bars = BarSerializer(many=True, required=False)

    def create(self, validate_data):
        bars_data = validated_data.pop('bars', [])
        foo = Foo.objects.create(**validated_data)

        for bar_data in bars_data:
            Bar.objects.create(foo=foo, **bar_data)

        return foo

    def update(self, instance, validated_data):
        bars_data = validated_data.pop('bars', None)
        if bars_data is not None:
            Bar.objects.filter(foo=instance).delete()
            for bar_data in bars_data:
                Bar.objects.create(foo=instance, **bar_data)

        return super().update(instance, validated_data)

    class Meta:
        model = Foo
        fields = ('bars',)

创建对象时,我得到了预期的结果,但是每当我要更新条形列表而不提供create_date时,都会收到一条错误消息,指出create_date不能为None (正确):

  

django.db.utils.IntegrityError:NOT NULL约束失败:myapp_bar.create_date

如果我在bars_data内打印update,我会发现它没有从timezone.now获得默认值。它根本不在字典中。

如何在此处访问默认值?它应该已经通过了序列化程序的验证,为什么没有添加默认值?

2 个答案:

答案 0 :(得分:1)

来自docs

  

default在部分更新操作期间未应用。在部分更新的情况下,仅输入数据中提供的字段将返回经过验证的值。

因此,您将不得不手动添加值:

Bar.objects.create(foo=instance, **bar_data, create_date=timezone.now)

答案 1 :(得分:0)

您会收到此错误,因为在Bar模型中,create_date属性具有null = False,如果要使用默认值,请像下面这样在Bar模型上的create_date属性中使用auto_now or auto_now_add参数:

class Bar(models.Model):
    ...
    created_date = models.DateField(auto_now_add=True)

每次创建Bar的新实例时,都会自动添加create_date。