当需要模型中的字段时,如何在序列化器上允许空值?

问题描述 投票:0回答:1

鉴于 Django (DRF) 中的以下

payload
models.py
serializers.py

payload

{
  "created_by": 6,
  "brand": 1,
  "foo_details": [
    {
      "quantity": 123,
      "price_estimation": 456
    },
    {
      "quantity": 789,
      "price_estimation": 1011
    }
  ]
}

models.py

class Foo(models.Model):
    created_by = models.ForeignKey(CustomUser, on_delete=models.PROTECT)
    brand = models.ForeignKey(Brand, on_delete=models.SET_NULL, null=True)
    # OTHER FIELDS HERE

class FooChild(models.Model):
    foo = models.ForeignKey(Foo, on_delete=models.CASCADE, related_name="foo_details")
    quantity = models.PositiveIntegerField(default=0)
    price_estimation = models.PositiveIntegerField(default=0)
    # OTHER FIELDS HERE

serializers.py

class FooChildSerializer(serializers.ModelSerializer):
    # foo = serializers.PrimaryKeyRelatedField(read_only=True, required=False) -> LINE 2

    class Meta:
        model = FooChild
        fields = ["id", "foo", "quantity", "price_estimation", ...]

class FooSerializer(serializers.ModelSerializer):
    # foo_details = FooChildSerializer(many=True) -> LINE 9
    # foo_details = serializers.DictField(child=serializers.CharField(), many=True) -> LINE 10

    class Meta:
        model = Foo
        fields = ["id", "created_by", "brand", "foo_details", ...]

    def create(self, validated_data):
        # I want to save the payload to `Foo` and `FooChild` inside this function at the same time, below is my unsuccessful attempt

        # print(validated_data)
        # validated_data.pop("foo_details")
        # foo = Foo.objects.create(**validated_data) -> LINE 21
        # foo_child = FooChild.objects.create(foo=foo)
        
        # return foo

我现在遇到的问题是,当我尝试POST有效负载时,DRF抱怨

foo
中的
FooChild
字段是必需的,这是可以理解的,问题是,
id
Foo
仅在我创建
foo
实例(第 21 行)后才存在。我试图告诉 DRF 在创建
foo
时忽略提供
FooChild
的要求,但无济于事(参见上面的第 2、9、10 行)。我该如何解决这个问题?

实际上我有一个想法,在

null=True
模型中设置
FooChild
,但是没有
FooChild
Foo
就不可能存在,所以我认为这没有任何意义。谢谢你的帮助

python json django django-rest-framework django-serializer
1个回答
0
投票

要允许

foo
序列化器中的
FooChild
字段为空值,同时保留模型中所需的字段,您可以按如下方式修改代码:

  1. FooChildSerializer
    中,删除
    foo
    字段声明。
class FooChildSerializer(serializers.ModelSerializer):
    class Meta:
        model = FooChild
        fields = ["id", "quantity", "price_estimation", ...]
  1. FooSerializer
    中,保存
    foo_details
    实例后更新
    FooChild
    字段以处理
    Foo
    实例的创建。
class FooSerializer(serializers.ModelSerializer):
    foo_details = FooChildSerializer(many=True, required=False)

    class Meta:
        model = Foo
        fields = ["id", "created_by", "brand", "foo_details", ...]

    def create(self, validated_data):
        foo_details_data = validated_data.pop("foo_details", None)

        foo = Foo.objects.create(**validated_data)

        if foo_details_data:
            for foo_detail_data in foo_details_data:
                FooChild.objects.create(foo=foo, **foo_detail_data)

        return foo

通过在序列化器中为

required=False
字段设置
foo_details
,它允许该字段在有效负载中是可选的。在
create
方法中,我们使用
foo_details
validated_data
中提取
pop
数据,如果不存在则保留
None

创建

foo
实例后,我们检查
foo_details_data
是否存在。如果是,我们迭代数据并创建
FooChild
实例,将它们与
foo
实例关联起来。

通过这种方式,您可以创建一个

Foo
实例,无论是否在负载中提供
foo_details
。如果提供了
foo_details
,它们将在创建后与
Foo
实例关联。

© www.soinside.com 2019 - 2024. All rights reserved.