Получить аннотированную сумму с вычислением в django

#django

#django

Вопрос:

У меня есть данные, подобные приведенным ниже. Необходимо получить итоговое значение путем вычисления price - discount% и суммы всех. Как использовать aggregate здесь

Данные

models.py

 class Order(TimeStamp):    
    code = models.CharField(max_length=255, null=True, blank=True)

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True, blank=True, related_name='order_item')
    name = models.CharField(max_length=255, null=True, blank=True)
    discount = models.FloatField(null=True, blank=True)
    price = models.FloatField(null=True, blank=True)

    def __str__(self):
        return self.name
  

Комментарии:

1. Пожалуйста, поделитесь соответствующей моделью (моделями).

2. @WillemVanOnsem пожалуйста, проверьте

Ответ №1:

Вы можете рассчитать сниженную цену для каждого товара через .annotate(…) [Django-doc]:

 from django.db.models import F, Sum

OrderItem.objects.annotate(
    total=F('price') * 0.01 * (100-F('discount'))
)['total']  

Если вы хотите суммировать цены со скидкой, мы можем использовать Sum выражение [Django-doc]:

 from django.db.models import F, Sum

OrderItem.objects.aggregate(
    total_price=Sum(F('price') * 0.01 * (100-F('discount')))
)['total_price']  

или для определенного порядка:

 from django.db.models import F, Sum

myorder.order_item.aggregate(
    total_price=Sum(F('price') * 0.01 * (100-F('discount')))
)['total_price']  

Вероятно, вы захотите сделать это для Order объекта:

 from django.db.models import F, Sum

Order.objects.annotate(
    total_price=Sum(F('order_item__price') * 0.01 * (100-F('order_item__discount')))
)  

Order Объекты, которые возникают в результате этого, будут иметь дополнительный атрибут .total_price , который содержит общую цену.


Примечание: я бы воздержался от создания большого количества (всех) полей NULL , доступных. Это означает, что если поля есть NULL , то также могут быть NULL выражения и агрегаты с этими полями, и часто так и есть, если одно из включенных полей есть NULL . Часто NULL доступные поля встречаются редко и используются, если допустимо наличие отсутствующей информации.


Примечание: related_name=… [Django-doc] — это имя менеджера для извлечения связанных объектов в обратном порядке. Поэтому обычно related_name ForeignKey или ManyToManyField является множественным числом, например, order_items вместо order_item .


Примечание: Возможно, имеет больше смысла работать с DecimalField [Django-doc], FloatField чем с [Django-doc],, поскольку десятичная дробь имеет фиксированную точность и меньше ошибок округления, особенно при работе с финансовыми данными, что является более точным.

Комментарии:

1. Спасибо за ваш ответ.