Django's annotate Count with division returns integer instead of float
Asked Answered
D

1

13

I have many objects and 3 of them have name='AAA'

I group them by 'name' and annotate num in group:

my_models = MyModel.objects.order_by('name').values('name').annotate(count=Count('name'))

for i in my_models:
    print(i.count, i.name)

I get:

3, 'AAA'
1, 'BBB'
...

Everything is fine, but when I try to add some formula to annotate Count():

my_models = MyModel.objects.order_by('name').values('name').annotate(count=Count('name') / 2)

I get:

1, 'AAA'
0, 'BBB'
...

But expected:

1.5, 'AAA'
0.5, 'BBB'
...

EDIT:

Python division differs from SQL division through Django's ORM, so 2/1 in python 3 returns 2.0 - OK, but not in SQL

Dividend answered 11/12, 2016 at 22:4 Comment(4)
How about / 2.0?Arst
@Arst No, python division and division from SQL differs :(Dividend
In Django 1.10 you can use Cast, see this answer. On Django 1.8+, you might be able to use ExpressionWrapper.Monophony
@Monophony big thx, man!Dividend
C
25

Full answer following @Alasdair's comment:

from django.db.models import FloatField
from django.db.models.functions import Cast

qs = MyModel.objects.order_by('name').values('name').annotate(
    count=Cast(Count('name') / 2.0, FloatField()))
Contrecoup answered 18/12, 2016 at 12:20 Comment(2)
@rluts , try to cast both of variable first, example total=Cast(Count('id'), FloatField() / Cast(Count('id'), FloatField())Cremona
It isn't actually necessary to cast both - the way Python works is that if one of the values of an arithmetic expression is a float the result will be cast to float as well.Alvord

© 2022 - 2024 — McMap. All rights reserved.