Reputation: 3018
I have a model that has a type and value, based on the type I want to change the sign of the number to negative (Without changing it in the database)
class Foo(models.Model):
EARNING_CATEGORY = 'E'
DEDUCTION_CATEGORY = 'D'
CATEGORY_CHOICES = (
(EARNING_CATEGORY, 'Earning'),
(DEDUCTION_CATEGORY, 'Deduction'),
)
name = models.CharField(max_length=50)
category = models.CharField(max_length=1, choices=CATEGORY_CHOICES)
value = models.FloatField()
Now in order to aggregate over Foo
I need to consider that values with category = D
should be negative so I get the real sum.
What I tried so far is to change the sign during the save()
method, but I don't want to show it to the user as negative in the application. So the only way I came up with is to calculate in a method using a for loop.
class Account(models.Model):
# feilds
def sum(self):
items = self.foo_set.all()
sum = 0
for i in items:
if i.category == Foo.DEDUCTION_CATEGORY:
sum -= i.value
else:
sum += i.value
return sum
Upvotes: 1
Views: 50
Reputation: 2146
You can annotate the current sign during your query like this:
from django.db.models import Case, Value as V, F, FloatField, When
items = self.foo_set.annotate(fixed_value=Case(
When(category=Foo.DEDUCTION_CATEGORY, then=V('-1')*F('value')),
default=F('value'),
output_field=FloatField())
).all()
So during annotation we do a condition check and if our category is equal to 'D', we change sign of value
field, and then do your aggregation on fixed_value
field.
And here's more info: https://docs.djangoproject.com/en/1.9/ref/models/conditional-expressions/#case
Upvotes: 3