How to perform a mathematical operation on two instances of object in Django?

Question:

I want to add two numbers from two different objects.

Here is a simplified version. I have two integers and I multiply those to get multiplied .

models.py:

class ModelA(models.Model):
    number_a = models.IntegerField(default=1, null=True, blank=True)
    number_b = models.IntegerField(default=1, null=True, blank=True)

    def multiplied(self):
        return self.number_a * self.number_b

views.py:

@login_required
def homeview(request):

    numbers = ModelA.objects.all()

    context = {
        'numbers': numbers,
    }
    return TemplateResponse...

What I’m trying to do is basically multiplied + multiplied in the template but I simply can’t figure out how to do it since I first have to loop through the objects.

So if I had 2 instances of ModelA and two 'multiplied' values of 100 I want to display 200 in the template. Is this possible?

Asked By: Vinko Oakniiv

||

Answers:

You can try doing that with aggregate

from django.db.models import Sum

ModelA.objects.aggregate(Sum('multiplied'))

If that does not suit you just use aggregate on each field and then add them together.

Answered By: haduki

In your template, when you do a forloop over the numbers variable, you can directly access properties, functions and attributes.

So to access the value you want I guess it would look something like this, simplified:

{% for number in numbers %}
    {{ number.multiplied }}
{% endfor %}

Hope that makes sense?

However, please take note that this is not the most efficient method.

We can make Django ask the SQL server to do the heavy lifting on the calculation side of things, so if you want to be really clever and optimise your view, you can comment out your multiplied function and replace then, you still access it in the template the same way I described above, but we needs to change the code in your view slightly like so:

numbers = ModelA.objects.aggregate(Sum('number_a', 'number_b'))

As described loosely in haduki’s answer. This offloads the calculation to the SQL server by crafting an SQL query which uses the SUM SQL database function, which for all intents and purposes is almost always going to be substantially faster that having a function on the object.

Answered By: Swift

The good practice is always to avoid logic on the template. It would be better to loop at the view and add calculated value to context:

def homeview(request):
    queryset = ModelA.objects.all()
    multipliers_addition = 0
    for obj in queryset:
        multipliers_addition += obj.multiplied()

    context = {
        'addition': multipliers_addition,
    }

    return render(request, 'multiply.html', context)
Answered By: Niko
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.