Правильный способ иметь вложенную записываемую сериализацию django drf - PullRequest
0 голосов
/ 21 октября 2018

Предположим, что у меня есть две модели с двумя сериализаторами, одна имеет другую как вложенный сериализатор, как показано ниже:

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;

1 Ответ

0 голосов
/ 21 октября 2018

вы также можете использовать сериализатор элементов для создания элементов в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...