Предположим, что у меня есть две модели с двумя сериализаторами, одна имеет другую как вложенный сериализатор, как показано ниже:
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)
Как вы можете видеть для такого сценария, мне пришлось дважды писать один и тот же коддля создания элемента один в сериализаторе элементов, а другой - в сериализаторе счетов, это противоречит правилу СУХОЙ, и это может стать более сложным и подверженным ошибкам по мере продвижения кода.Я ищу способ написать этот код только один раз и использовать его в обоих местах.
Возможно, использование метода класса в ItemSerializer
- это решение, но не полное решение, там у вас не так много ItemSerializer
методов ичлены, которые могут вам понадобиться. Я думаю, что наилучшее из возможных решений - это создание сериализатора не с необработанными данными, а с проверенными, потому что в методе Billing
create у нас есть проверенные данные элемента.
Iиспользую django 1.11 и DRF 3.8.2;