Django,两个注释结果之间的除法无法正确计算
Django, division between two annotate result won't calculate correctly
我试图在查询集中的两个注释结果之间进行划分。印象比点击大得多,所以我应该得到小数点后十位。
def get_queryset(self):
return googleData.objects.filter(account=self.account_name).\
values('date').\
annotate(Sum('click'), Sum('impression'), Sum('converted_click'),
Sum('conversion_value'), Sum('cost'), Sum('conversion_value'), ctr_monthly= Sum('click')/Sum('impression')).\
order_by('-date')
这里有问题:
ctr_monthly= Sum('click')/Sum('impression'))
在模板中我有:
<td>{{ googleData.ctr_monthly | floatformat:2}} </td>
结果是 0.00。
如果我做 ctr_final = click * impression,它会正确生成。
Click & Impression 均为整数字段。
我尝试使用 float(),但出现语法错误。
另一个问题是:制作这样的查询集的最佳做法是什么?有什么办法可以把它分解成几段短代码,使它更整洁、更易读吗?
谢谢~
据我所知,没有办法使用 ORM 来做到这一点。
Sum()
函数 return 与放入其中的字段类型相同(即 IntegerField() 总是 return 一个整数)。您可以使用 ExpressionWrapper
之类的函数强制输出为浮点数,但这在这种情况下无济于事,因为为时已晚:两个整数的除法已经 return ing 另一个整数。
要解决您的问题,请从查询中删除 ctr_monthly
部分,并创建一个简单的模板标记,将两个数字转换为浮点数并将它们相除。
您的模板将如下所示:
<td>{{ monthly_ctr(googleData.click, googleData.impression) | floatformat:2}} </td>
对于较新版本的 Django,您可以使用新的 Func
对象在 Sum
.[=18= 之前将值转换为 FloatFields
或 DecimalFields
]
from django.db.models.functions import Cast
from django.db.models import FloatField
ctr_monthly= Cast(Sum('click'), FloatField())/Cast(Sum('impression')), FloatField())
即使使用旧版本的 Django,您也可以在注释 ctr_monthly 之前在 Sum
上指定 output_field
,如下所示:
from django.db.models import F
def get_queryset(self):
return googleData.objects.filter(
account=self.account_name
).values('date').annotate(
click_sum=Sum(
'click',
output_field=FloatField()
),
impression_sum=Sum(
'impression',
output_field=FloatField()
),
converted_click_sum=Sum('converted_click'),
conversion_value_sum=Sum('conversion_value'),
cost_sum=Sum('cost')
).annotate(
ctr_monthly=F('click_sum') / F('impression_sum')
).order_by('-date')
我试图在查询集中的两个注释结果之间进行划分。印象比点击大得多,所以我应该得到小数点后十位。
def get_queryset(self):
return googleData.objects.filter(account=self.account_name).\
values('date').\
annotate(Sum('click'), Sum('impression'), Sum('converted_click'),
Sum('conversion_value'), Sum('cost'), Sum('conversion_value'), ctr_monthly= Sum('click')/Sum('impression')).\
order_by('-date')
这里有问题:
ctr_monthly= Sum('click')/Sum('impression'))
在模板中我有:
<td>{{ googleData.ctr_monthly | floatformat:2}} </td>
结果是 0.00。 如果我做 ctr_final = click * impression,它会正确生成。 Click & Impression 均为整数字段。
我尝试使用 float(),但出现语法错误。
另一个问题是:制作这样的查询集的最佳做法是什么?有什么办法可以把它分解成几段短代码,使它更整洁、更易读吗?
谢谢~
据我所知,没有办法使用 ORM 来做到这一点。
Sum()
函数 return 与放入其中的字段类型相同(即 IntegerField() 总是 return 一个整数)。您可以使用 ExpressionWrapper
之类的函数强制输出为浮点数,但这在这种情况下无济于事,因为为时已晚:两个整数的除法已经 return ing 另一个整数。
要解决您的问题,请从查询中删除 ctr_monthly
部分,并创建一个简单的模板标记,将两个数字转换为浮点数并将它们相除。
您的模板将如下所示:
<td>{{ monthly_ctr(googleData.click, googleData.impression) | floatformat:2}} </td>
对于较新版本的 Django,您可以使用新的 Func
对象在 Sum
.[=18= 之前将值转换为 FloatFields
或 DecimalFields
]
from django.db.models.functions import Cast
from django.db.models import FloatField
ctr_monthly= Cast(Sum('click'), FloatField())/Cast(Sum('impression')), FloatField())
即使使用旧版本的 Django,您也可以在注释 ctr_monthly 之前在 Sum
上指定 output_field
,如下所示:
from django.db.models import F
def get_queryset(self):
return googleData.objects.filter(
account=self.account_name
).values('date').annotate(
click_sum=Sum(
'click',
output_field=FloatField()
),
impression_sum=Sum(
'impression',
output_field=FloatField()
),
converted_click_sum=Sum('converted_click'),
conversion_value_sum=Sum('conversion_value'),
cost_sum=Sum('cost')
).annotate(
ctr_monthly=F('click_sum') / F('impression_sum')
).order_by('-date')