1

さまざまなデータベース モデル フィールドを含む Django モデルがあります。マネージャーのクエリセットの 1 つは、いくつかの注釈呼び出しを介してさまざまな集計を取得します。これらの注釈の一部はカスタムメイドで、データベースから float 値を取得します。これらの注釈は、モデルのフィールドの一部ではありません。ただし、クエリセットが作成されると、これらの浮動小数点数はモデル内の整数であることがわかります。浮動小数点数または小数データ型にバインドするモデル フィールドがないためだと思います。

私が何を意味するかを説明するためのコードを次に示します。

カスタム集約クラス。データベースが結果を 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 を float として返し、float としてソートし、適切にフィルタリングしますが (生成された SQL を Postgres のコンソールで実行すると)、結果の Queryset は値を整数に変換し、結果として0s... (CTR はモデル フィールドではないことに注意してください)。

注釈付きの値が正しいデータ型でモデルに読み込まれるようにするにはどうすればよいですか? タイプを保持する DecimalField または FloatField の非データベース モデル フィールドを設定できますか?

どんなアイデアでも大歓迎です!
ありがとう
ハレル

4

3 に答える 3

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.
于 2010-09-06T12:15:03.713 に答える
0

このコードは、以下の Omer の提案を試した後、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'>)  
于 2010-09-03T11:01:45.687 に答える
0

djangoコードのドキュメントによると:

source は、列参照の基礎となるフィールドまたは集計定義です。集計が序数型または計算型でない場合、この参照は集計の強制出力型を決定するために使用されます。

そこで、SqlCTR のコンストラクターでソースにフィールドの型を入れてみてください。

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

次のようにする必要があります。

aggregate = SqlCTR(col, source=models.DecimalField(), is_summary=is_summary)
于 2010-09-02T21:55:46.387 に答える