Как агрегировать сумму поля модели класса в django
Я безуспешно пытаюсь показать total_net_interest
на моей приборной панели. Я думаю, что это проблема с моей стратегией. Есть ли у кого-нибудь решение этой проблемы?
Модель
class Investment(models.Model):
PLAN_CHOICES = (
("Basic - Daily 2% for 182 Days", "Basic - Daily 2% for 182 Days"),
("Premium - Daily 4% for 365 Days", "Premium - Daily 4% for 365 Days"),
)
plan = models.CharField(max_length=100, choices=PLAN_CHOICES, null=True)
principal_amount = models.IntegerField(default=0, null=True)
investment_id = models.CharField(max_length=10, null=True, blank=True)
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now=True, null=True)
due_date = models.DateTimeField(null=True, blank=True)
def daily_interest(self):
if self.plan == "Basic - Daily 2% for 182 Days":
return self.principal_amount * 365 * 0.02/2/182
else:
return self.principal_amount * 365 * 0.04/365
def net_interest(self):
if self.plan == "Basic - Daily 2% for 182 Days":
return self.principal_amount * 365 * 0.02/2
else:
return self.principal_amount * 365 * 0.04
def total_net_interest(self):
return self.Investment.aggregate(total_net_interest=Sum('net_interest'))['total_net_interest']
Как указано в комментариях, вы не можете агрегировать с помощью метода модели - однако, вы можете добавить net_interest
в кверисет с помощью аннотации и затем агрегировать аннотированное поле.
Django .aggregate() на .annotate()
Вам, вероятно, потребуется использовать Case
и When
, чтобы применить вашу логику из этого метода.
Кроме того, в вашей модели PLAN_CHOICES
скопированы оба значения, лучше было бы написать примерно так:
PLAN_BASIC = "basic"
PLAN_PREMIUM = "premium"
PLAN_CHOICES = (
(PLAN_BASIC, "Basic - Daily 2% for 182 Days"),
(PLAN_PREMIUM, "Premium - Daily 4% for 365 Days")
)
Это означает, что в базе данных хранятся только "basic" и "premium", но при этом будут отображаться введенные вами строки. Вы можете сделать что-то вроде Investment.PLAN_BASIC
или self.PLAN_BASIC
, в зависимости от контекста, чтобы убедиться, что вы не вводите строки в нескольких местах.
Вы должны annotate
интересы в наборе запросов агрегировать на этой аннотации:
from django.db.models import Case, F, FloatField, Q, Sum, When
total = (Investment
.objects
.annotate(net=Case(When(Q(plan='Basic - Daily 2% for 182 Days'),
then=F('principal_amount') * 365 * 0.01),
default=F('principal_amount') * 365 * 0.04,
output_field=FloatField))
.aggregate(total=Sum('net')))['total']