鉴于 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
就不可能存在,所以我认为这没有任何意义。谢谢你的帮助
要允许
foo
序列化器中的 FooChild
字段为空值,同时保留模型中所需的字段,您可以按如下方式修改代码:
FooChildSerializer
中,删除 foo
字段声明。class FooChildSerializer(serializers.ModelSerializer):
class Meta:
model = FooChild
fields = ["id", "quantity", "price_estimation", ...]
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
实例关联。