2016-05-07 6 views
5

を丸め避けるために、どのように私はこのコードを持っている:ジャンゴF()部門 -

q = MyModel.objects.order_by('-value1').annotate(
      res=ExpressionWrapper(
       (F('value1')/F('value2')), 
       output_field=FloatField()), 
      ) 

for i in q:           
    print(i.value1, i.value2, i.res) 

ので、出力は次のようになります。

5 10 0.0 
1 2 0.0 

しかし、私は

5 10 0.5 
1 2 0.5 

が必要Wy F()結果を丸めましたか?これをしないとどうですか?

ありがとうございます!

+0

あなたは 'float(F( 'value1'))'を試しましたか? – trantu

+2

'F'式に関することは、Pythonが値を知りませんが、操作(この場合は除算)をデータベースに渡すことです。 PostgreSQLとMySQLの場合、整数除算はPython 2.xのように整数になります。 – schwobaseggl

+0

@trantu float()の引数は文字列でなければなりません。 'F'ではなく数字でなければなりません。 – tim

答えて

3

あなたが期待している結果は、生のクエリで達成するのは本当に簡単で、本当に純粋なdjangoで実現するのは本当に難しいです。

from django.db.models import FloatField, ExpressionWrapper, F 

template = '%(function)s(%(expressions)s AS FLOAT)' 
fv1 = Func(F('value1'), function='CAST', template=template) 
fv2 = Func(F('value2'), function='CAST', template=template) 
ew = ExpressionWrapper(fv1/fv2, output_field = FloatField()) 


q = MyModel.objects.order_by('-value1').annotate(res = ew) 

これは優雅であると非難するのではなく、MysqlとPostgresqlの両方で動作します。

背景を提供します。丸めは、データベースが整数部をにすることによって行われます。なぜなら、あなたが持つフィールドはintであるからです。小数点以下の桁数を必要とする場合は、小数点以下桁数にキャストする必要があります。残念なことに、Djangoでのキャストはあまり簡単ではありません。

PostgreSQLは、実際にはエレガントな方法でfloatにキャストします。 value1 :: floatしかし、これは内部のdjangoから(少なくとも私が知っている限り)使用することはできません

10

F()は、1つの要素を10進数に変換する乗算をサポートしています。私はこれよりエレガントな方法は、その後をvalue1、フィールド上の生のSQLのCASTを書き込み、その後、分裂を行う見つける

from decimal import Decimal 

q = MyModel.objects.order_by('-value1').annotate(
      res=ExpressionWrapper(
       (F('value1') * Decimal('1.0')/F('value2')), 
       output_field=FloatField()), 
      ) 

組み合わせ式は次のようになります。

+0

私はあなたにupvoteを与えようとしていませんが、これはTypeErrorを生成しました:unboundメソッドselect_format()はFloatFieldインスタンスを最初の引数として呼び出さなければなりません(代わりにSQLCompilerインスタンスを取得) – e4c5

+0

@ e4c5もう少し特定の情報(django ver、db backedなど)?私はDjango 1.8とPostgresでテストしました。正しいSQLを生成する: 'django.db.connection [-1] ['sql'] == SELECT ...(" shop_product "。" value1 "* 1.0)/" shop_product "。" value2 ")AS" res "FROM ... '。 'res'には、value1 == 2、value2 == 3のとき、0.6666666666666666のような正しい小数の結果が含まれます。 – joanbm

+0

django 1.9 postgresql 9.5申し訳ありませんが、db – e4c5