атрибут доступа через сериализатор django - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть следующие модели:

class OrderItem(models.Model):
    ordered_amount = models.IntegerField(validators=[MinValueValidator(0)])
    amount = models.IntegerField(default=0)

    order = models.ForeignKey(
        Order, on_delete=models.CASCADE, related_name="order_items"
    )

class Order(models.Model):
    reference = models.CharField(max_length=50)
    purchase_order = models.CharField(max_length=15, blank=True, null=True)

Я сейчас пишу сериализатор для распечатки заказов. В этом OrderSerializer мне нужно получить доступ к количеству и order_amount в классе OrderItem. Как мне это сделать? Это то, что у меня сейчас:

class AdminOrderListSerializer(serializers.ModelSerializer):
    amount = serializers.IntegerField()
    ordered_amount = serializers.IntegerField()

    class Meta:
        model = Order
        fields = [
            "purchase_order",
            "reference",
            "amount",
            "ordered_amount",
        ]

    # noinspection PyMethodMayBeStatic
    def validate_amount(self, order):
        if order.order_items.amount:
            return order.order_items.amount
        return

    # noinspection PyMethodMayBeStatic
    def validate_ordered_amount(self, order):
        if order.order_items.ordered_amount:
            return order.order_items.ordered_amount
        return

Это дает мне следующую ошибку:

AttributeError: Получил AttributeError при попытке получить значение для поля amount на сериализаторе AdminOrderItemListSerializer. Поле сериализатора может иметь неправильное имя и не соответствовать ни одному атрибуту или ключу в экземпляре Order. Исходный текст исключения был: объект «Заказ» не имеет атрибута «сумма».

1 Ответ

1 голос
/ 29 апреля 2020

Существует много способов, один из которых SerializerMethodField:

from django.db.models import Sum

class AdminOrderListSerializer(serializers.ModelSerializer):
    amount = serializers.SerializerMethodField()
    ordered_amount = serializers.SerializerMethodField()

    def get_amount(self,obj):
        return obj.order_items.aggregate(sum=Sum('amount'))['sum']


    def get_ordered_amount(self,obj):
        return obj.order_items.aggregate(sum=Sum('order_amount'))['sum']

Оптимизированное решение

Другой способ Для этого необходимо annotate получить данные для набора запросов и получить к ним доступ в сериализаторе. Для этого вам нужно изменить представление:

class SomeView(ListAPIView):
    queryset = Order.objects.annotate(amount=Sum('order_items__amount'),order_amount=Sum('order_items__order_amount'))

Это оптимизированное решение, поскольку оно уменьшает попадания в базу данных (оно происходит только один раз).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...