Complex filter with multiplications in the Django model

Asked

Viewed 111 times

0

I have a doubt that I have from the beginning of a project that I am developing and I have not yet found an answer...

I have 2 models in my project in Django:

class Turma(models.Model):
    nome = models.CharField(max_length = 50)

class Pessoa(models.Model):
    turma = models.ForeignKey(Turma, on_delete = models.CASCADE)
    multiplicador = models.DecimalField(max_digits = 5, decimal_places = 2)

Supposing I had a class with 20 people in it, if I wanted the sum of all the multipliers, it would be something like this:

from django.db.models import Sum
turma = Turma.objects.get(pk = 1)
soma = turma.pessoa_set.aggregate(soma = Sum('multiplicador'))['soma']

But what if I want to multiply all multipliers? There is a way to achieve this without having to appeal to a go with prefetch_related?

1 answer

0

You can create an Aggregate function in your database first as specified in this answer

CREATE AGGREGATE MUL(bigint) ( SFUNC = int8mul, STYPE=bigint );

Then you can create a function Aggregate that will use the function you just created.

from django.db.models import Aggregate, IntegerField

class Multiplication(Aggregate):
    function = 'MUL'
    template = '%(function)s(%(distinct)s%(expressions)s)'

    def __init__(self, expression, distinct=False, **extra):
        super().__init__(
            expression,
            distinct='DISTINCT ' if distinct else '',
            output_field=IntegerField(),
            **extra
    )

This way you can call the function in Aggregate as you would in the sum

soma = turma.pessoa_set.aggregate(soma = Sum('multiplicador'))['soma']
mult = turma.pessoa_set.aggregate(mult = Multiplication('multiplicador'))['mult']

Note that this function depends on the size of the Bigint postgres (if you are using it). Even more so in the case of a mutiplication in which the number grows rapidly.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.