2015-08-28 46 views
4

我正试图在queryset中的两个注释结果之间进行划分。印象比点击大得多,所以我应该得到十分数。Django,两个注释结果之间的分割将无法正确计算

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 *印象,它会正确生成。 Click &印象都是整数场。

我试过使用float(),给了我一个语法错误。

另一个问题是:建立这样一个查询集的最佳实践是什么?有什么办法可以将它分解成几段简短的代码,并使它更加整洁可读?

谢谢〜

回答

10

使用Django的新版本,你可以使用新的Func对象Sum前值转换为FloatFieldsDecimalFields

​​

即使使用旧版本的Django的,你也许可以ctr_monthly注释,像这样之前刚刚指定的Sumoutput_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') 
1

据我所知,没有办法做到这一点使用的ORM。

Sum()函数返回与放入它相同的字段类型(即IntegerField()将始终返回一个整数)。您可以使用像ExpressionWrapper这样的函数来强制输出为浮点数,但在这种情况下将不会有所帮助,因为它已经太迟了:两个整数的除法将已经返回另一个整数。

要解决您的问题,请从您的查询中删除ctr_monthly部分,然后创建一个简单的模板标记,将两个数字转换为浮点数并将其分开。然后

你的模板将是这样的: <td>{{ monthly_ctr(googleData.click, googleData.impression) | floatformat:2}} </td>

+0

这工作!谢谢。将所有内容都放在decimalField中是一种更好的做法吗? – viviwill