Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can't aggregate a DecimalField in Django

I have a queryset where I want to aggregate the fields amount which itself is a DecimalField. The target field is also a DecimalField.

I get this error:

django.core.exceptions.ValidationError: ["“{‘amount__sum’: Decimal(‘3821.02000000000’)}” value must be a decimal number."]

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Why does it say it must be a decimal number even though it is a DecimalField?

# models.py

class Payment(models.Model):

    offer = models.ForeignKey(Offer, on_delete=models.CASCADE)
    month = models.ForeignKey(Period, on_delete=models.CASCADE)
    payroll_run = models.ForeignKey(Payroll, on_delete=models.CASCADE, null=True, blank=True)  # is populated once the payroll run was created

    amount = models.DecimalField(decimal_places=2, max_digits=10)


class Payroll(models.Model):

    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    month = models.DateField()
    amount = models.DecimalField(decimal_places=2, max_digits=10)
    line_items = models.PositiveIntegerField()
def test():
   ...

    # Loop the companies
    for company in qs_companies:
        # Query all Payments of that company in that month
        qs_payments = Payment.objects.filter(offer__company=company).filter(month=period)

        # Create a payroll run instance
        payroll_run = Payroll.objects.create(
            company=company,
            month=next_payroll_run,
            amount=qs_payments.aggregate(Sum('amount')),
            line_items=qs_payments.count()
        )

        payroll_run.save()
   ...

>Solution :

aggregate() returns a dictionary, you need to pass your aggregated value and not the whole dict

        payroll_run = Payroll.objects.create(
            company=company,
            month=next_payroll_run,
            amount=qs_payments.aggregate(Sum('amount'))['amount__sum'], # <- added the lookup
            line_items=qs_payments.count()
        )

EDIT: From Django 4.0 you can add a default argument to Sum

amount=qs_payments.aggregate(Sum('amount', default=Decimal(0)))['amount__sum']
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading