Управляйте данными на сериализаторе перед созданием экземпляра модели в DangoRestFramework - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть три родственные модели как таковые

Заказать модель

class Order(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    Name  =  models.CharField(max_length=250)
    orderType = models.ForeignKey(OrderType, on_delete=models.CASCADE, null=True)

    class Meta:
        ordering = ['id']
    def __str__(self):
        return '{}'.format(self.Name)enter code here

Модель заказа

class OrderPricing(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    TotalPrice =  models.DecimalField(decimal_places=2, max_digits=10)
    #related field
    order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True)

    class Meta:
        ordering = ['order']
    def __str__(self):
        return self.TotalPrice

Тип модели заказа

class OrderType(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    Name = models.CharField(max_length = 100)
    Premium =  models.BooleanField()

    class Meta:
        ordering = ['id']
  1. Давайте проигнорируем порядок появления моделей выше.
  2. У меня есть три SerializerModel для каждой модели.
  3. Я могу выбрать любую модель на BrowsableAPI

Q1:

С помощью browsableAPI я могу создать Заказ.

Я еще не дошел до «Записываемого вложенного сериализатора», и я думаю, что Django обнаружил это в своих документах через класс drf-writable-nested.

У меня есть два типа заказа

1 = {'Не премиум': 'Ложь'} # не премиум

2 = {'Premium': 'True'} # Premium

Предположим, у меня есть переменная order_price = 5 # £ 5

Как я могу

  1. Создать заказ,
  2. Если заказ премиум, установите для order_price значение 10 #order_price * 2
  3. Если заказ НЕ премиум, установите для order_price значение 5
  4. Создайте экземпляр OrderPricing, связанный с заказом. Также передайте переменную order_price свойству TotalPrice при создании экземпляра

из того, что я видел и пробовал, я могу переопределить Create () на сериализаторе как таковом

class OrderSerializer(WritableNestedModelSerializer):
    """OrderSerializer"""
    # orderPricing = OrderPricingSerializer(required=False)

    class Meta:
        model = Order
        fields = ('__all__')

    def create(self, validated_data):
        #create instance of order
        #determine of order is premium
        typeid = uuid.UUID(validated_data.pop('orderType'))#get FK value
        isPremium = OrderType.objects.get(id = str(typeid.id))#determine if **Premium** is True/False

        # set/calculate the price of the order
        #create a related instance of OrderPricing

Q2 Я знаю о GenericViews и CreateModelMixin, но я не знаю, что лучше - переопределить .create () в сериализаторе или переопределить метод CreateModelMixin в GenericView

.

1 Ответ

0 голосов
/ 02 ноября 2018

Ну, где поставить бизнес-логику, всегда сложно ответить. У вас есть несколько мест, где это может быть - просмотр, сериализатор, модель или какой-то другой отдельный модуль / сервис.

У всех есть свои плюсы и минусы. Вы можете найти много статей на эту тему.

Но в вашем случае я бы, вероятно, выбрал perform_create вашего взгляда и создал бы в сериализаторе метод, который бы обновлял цену. Если бы мне нужно было использовать код для обновления цены, я бы перешел к отдельному общедоступному модулю и вызвал его оттуда.

Допустим, вы используете CreateModelMixin или лучше ListCreateAPIView

class YourView(ListCreateAPIView):
    serializer = OrderSerializer
    queryset = your_queryset

    def perform_create(self, serializer):
         serializer.update_price()
         serializer.save()

perform_create вызывается после проверки данных, поэтому вы можете получить доступ к проверенным данным.

update_price - ваш код, где вы обновляете цену.

Вы можете поспорить, чтобы переместить эту логику в метод создания или сохранения сериализатора, но они делают много других вещей, поэтому, если вам не нужно переопределять эти методы по другим причинам, вы можете воспользоваться perform_create методом.

...