1

Is it possible to annotate with complex value?

Like if I have table

class Test(models.model):
   value = models.PositiveIntegerField(_('value'))

next = 5
import math
Test.objects.annotate(new_field=math.sqrt(next-value)/math.atan(value))

2 Answers 2

2

No, you can't pass math functions into annotate().

If you want to do this calculation in Test model then create a method:

class Test(models.model):
    value = models.PositiveIntegerField(_('value'))

    def calc_value(self, next):
        return math.sqrt(next-self.value)/math.atan(self.value))

for t in Test.objects.all():
    print t.value. t.calc_value(5)

But if you want to use this calculation to order the queryset then you have to do the math at SQL level:

next = 5
Test.objects.extra(select={'new_field': 'SQRT(%d-value)/ATAN(value)' % next}) \
            .order_by('new_field'))

To filter the queryset by new field use where argument of the same extra() method:

Test.objects.extra(select={'new_field': 'SQRT(%d-value)/ATAN(value)' % next},
                   where=['new_field > 10'])

SQLite doesn't support math functions by default but with Postgres and MySQL this code should work just fine.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. Exactly what I wanted. Is there any way to filter by this new_field ins where clause? Or I can apply filter method?
You have to use extra(where=[...]). See the updated answer.
Fantastic. Exactly what I wanted!
0

No, annotations can only be done on django aggregations.

Annotates each object in the QuerySet with the provided list of aggregate values (averages, sums, etc) that have been computed over the objects that are related to the objects in the QuerySet.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.