2010-09-02 71 views
1

我有一个包含各种数据库模型字段的Django模型。 其中一个管理器的查询集通过一些批注调用检索各种聚合。其中一些注释是自定义的,并从数据库中检索浮点值。这些注释不是模型字段的一部分。 但是,当queryset被创建时,那些浮点数就变成了模型中的整数,我想是因为没有模型字段将它们绑定到float或decimal数据类型。如何将非数据库字段添加到数据库驱动的Django模型中,并通过保存其数据类型的QuerySet进行设置?

下面是一些代码在于向世人证明了我的意思:

的自定义聚合类。注意数据库铸就结果为float:

class SqlCTR(aggregates.Sum): 
    is_ordinal = True 
    sql_function = 'SUM' 
    sql_template= "CASE WHEN sum(campaignmanager_adstats.impressions) > 0 THEN sum(campaignmanager_adstats.clicks)/sum(campaignmanager_adstats.impressions)::float ELSE 0::float END" 

class CTR(Sum): 
    name='CTR' 
    def add_to_query(self, query, alias, col, source, is_summary): 
     aggregate = SqlCTR(col, source=source, is_summary=is_summary) 
     query.aggregates[alias] = aggregate 

而这里的查询集:

camps = self.select_related(depth=3).\  
    annotate(impressions=Sum('ad__adstats__impressions'),\  
    clicks=Sum('ad__adstats__clicks'),\  
    ctr=CTR('ad__adstats__clicks'),\  
    exclude(**campaignExclude).\  
    filter(**campaignArgs).order_by(sortBy) 

的问题是,虽然查询本身运行正常,并返回CTR作为花车,排序,作为浮并过滤它就好(如果我在Postgres的控制台中运行生成的SQL),结果Queryset将该值转换为整数,结果为0 ... (记住CTR不是模型字段)。

我该如何确保注释值在其正确的数据类型中加载到模型中?我可以设置DecimalField或FloatField的非数据库模型字段,它将保留类型吗?

任何想法将不胜感激!
由于
Harel的

回答

0

我会回答我自己的问题: 结果(显然),通过django代码本身有很多帮助。 我SqlCTR电话有:is_ordinal = True这在Django的代码状态注释:

is_ordinal, a boolean indicating if the output of this aggregate 
      is an integer (e.g., a count) 

,而我需要is_computer=True

is_computed, a boolean indicating if this output of this aggregate 
      is a computed float (e.g., an average), regardless of the input 
      type. 
0

根据Django的代码的文档:

源是基础字段或聚集定义 列引用。如果聚合不是序数或 计算类型,则此引用用于确定聚合的强制 输出类型。

因此,请尝试将源字段类型放在SqlCTR的构造函数中。

aggregate = SqlCTR(col, source=source, is_summary=is_summary) 

应该是:

aggregate = SqlCTR(col, source=models.DecimalField(), is_summary=is_summary) 
+0

奥马尔,似乎并没有工作(虽然它非常有意义,我非常有希望)。 下一个评论是一个shell测试场景。请注意,计算结果应该是十进制的,但会以'int'(0)形式出现。 我试过FloatField以及... – Harel 2010-09-03 10:56:59

+0

我似乎无法在评论中编写代码,所以我会将它添加到下面的新答案中 – Harel 2010-09-03 10:57:27

0

此代码试图奥马尔的提议之下......似乎无法写在评论中的任何代码后denomstrates从Django的壳输出...

>>> usr = User.objects.get(username='harel') 
>>> camps = Campaign.objects.campaigns(usr, {'ctr__gt':0, 'sort':'ctr','dir':'DESC'}) 
>>> for c in camps: 
...  print "%s:: %d/%d=%d (ctr type is %s)" % (c, c.clicks, c.impressions, c.ctr, str(type(c.ctr))) 
. .. 
Dan Schedule Test:: 10/15135=0 (ctr type is <type 'int'>) 
DTR-04-06:: 35/101827=0 (ctr type is <type 'int'>) 
US-Advertising-ad4:: 1/2991=0 (ctr type is <type 'int'>) 
Harels Test New Camp:: 51/153929=0 (ctr type is <type 'int'>) 
Commercial Team:: 161/512072=0 (ctr type is <type 'int'>) 
US-Marketing-ad3:: 1/3405=0 (ctr type is <type 'int'>) 
相关问题