拥有嵌套可写序列化 django drf 的正确方法
Proper way to have a nested writable serialization django drf
假设我有两个带有两个序列化器的模型,一个有另一个作为嵌套序列化器,如下所示:
class Item(models.Model):
...
discounts = ManyToManyField(Discount)
gift_discounts = ManyToManyField(GiftDiscount)
...
class Billing(models.Model):
...
items = ManyToManyField(Item)
...
# serializers
class ItemSerializer(serializers.ModelSerializer):
...
def create(self, validated_data):
discounts = validated_data.pop('discounts')
gift_discounts = validated_data.pop('gift_discounts')
item = super(ItemSerializer, self).create(**validated_data)
for discount in discounts:
item.discounts.add(discount)
for gift_discount in gift_discounts:
item.gift_discounts.add(gift_discount)
class BillingSerializer(serializers.ModelSerializer):
items = ItemSerializer(queryset=Item.objects.all(), many=True)
...
def create(self, validated_data):
items = validated_data.pop('items')
billing = super(BillingSerializer, self).create(**validated_data)
for item in items:
discounts = item.pop('discounts')
gift_discounts = item.pop('gift_discounts')
sell_item = Item.objects.create(**item)
for discount in discounts:
sell_item.discounts.add(discount)
for gift_discount in gift_discounts:
sell_item.gift_discounts.add(gift_discount)
如您所见,在这种情况下,我必须编写两次相同的代码,以在项目序列化程序中创建项目一个,在计费序列化程序中创建另一个项目,这违反了 DRY 规则,它可能会变得更加复杂且容易出错随着代码的推进。我正在寻找一种只编写一次代码并在两个地方都使用它的方法。
也许在 ItemSerializer
中使用 class 方法是一个解决方案,但不是完整的解决方案,您可能 need.I 认为 ItemSerializer
方法和成员不多最好的解决方案是创建一个序列化程序,不是使用原始数据,而是使用经过验证的数据,因为在 Billing
创建方法中我们有项目的经过验证的数据。
我正在使用 django 1.11 和 DRF 3.8.2;
您也可以使用项目序列化程序在 BillingSerializer 中创建项目,如下所示:
class BillingSerializer(serializers.ModelSerializer):
items = ItemSerializer(queryset=Item.objects.all(), many=True)
...
def create(self, validated_data):
items_validated_data = validated_data.pop('items')
instance = super(BillingSerializer, self).create(validated_data)
items = ItemSerializer(many=True).create(items_validated_data)
instance.items.set(items)
return billing
假设我有两个带有两个序列化器的模型,一个有另一个作为嵌套序列化器,如下所示:
class Item(models.Model):
...
discounts = ManyToManyField(Discount)
gift_discounts = ManyToManyField(GiftDiscount)
...
class Billing(models.Model):
...
items = ManyToManyField(Item)
...
# serializers
class ItemSerializer(serializers.ModelSerializer):
...
def create(self, validated_data):
discounts = validated_data.pop('discounts')
gift_discounts = validated_data.pop('gift_discounts')
item = super(ItemSerializer, self).create(**validated_data)
for discount in discounts:
item.discounts.add(discount)
for gift_discount in gift_discounts:
item.gift_discounts.add(gift_discount)
class BillingSerializer(serializers.ModelSerializer):
items = ItemSerializer(queryset=Item.objects.all(), many=True)
...
def create(self, validated_data):
items = validated_data.pop('items')
billing = super(BillingSerializer, self).create(**validated_data)
for item in items:
discounts = item.pop('discounts')
gift_discounts = item.pop('gift_discounts')
sell_item = Item.objects.create(**item)
for discount in discounts:
sell_item.discounts.add(discount)
for gift_discount in gift_discounts:
sell_item.gift_discounts.add(gift_discount)
如您所见,在这种情况下,我必须编写两次相同的代码,以在项目序列化程序中创建项目一个,在计费序列化程序中创建另一个项目,这违反了 DRY 规则,它可能会变得更加复杂且容易出错随着代码的推进。我正在寻找一种只编写一次代码并在两个地方都使用它的方法。
也许在 ItemSerializer
中使用 class 方法是一个解决方案,但不是完整的解决方案,您可能 need.I 认为 ItemSerializer
方法和成员不多最好的解决方案是创建一个序列化程序,不是使用原始数据,而是使用经过验证的数据,因为在 Billing
创建方法中我们有项目的经过验证的数据。
我正在使用 django 1.11 和 DRF 3.8.2;
您也可以使用项目序列化程序在 BillingSerializer 中创建项目,如下所示:
class BillingSerializer(serializers.ModelSerializer):
items = ItemSerializer(queryset=Item.objects.all(), many=True)
...
def create(self, validated_data):
items_validated_data = validated_data.pop('items')
instance = super(BillingSerializer, self).create(validated_data)
items = ItemSerializer(many=True).create(items_validated_data)
instance.items.set(items)
return billing