我有这段代码:
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 :(得分:13)
只需使用F()
支持乘法即可将一个因子转换为十进制数。
组合表达式看起来像:
from decimal import Decimal
q = MyModel.objects.order_by('-value1').annotate(
res=ExpressionWrapper(
(F('value1') * Decimal('1.0') / F('value2')),
output_field=FloatField()),
)
我发现这种更优雅的方式然后在value1字段上写入原始SQL CAST,然后进行除法。
答案 1 :(得分: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。
提供一些背景知识。舍入由数据库执行整数除法完成,因为您拥有的字段是整数。如果你想要十进制除法,你需要将它们转换为小数。不幸的是,使用Django进行投射并不容易。
Postgresql有一个非常优雅的方式来转换为浮动。 value1 :: float但是这不能在django里面使用(至少据我所知)
答案 2 :(得分:2)
不幸的是,ORM F('value1') / F('value2')
操作在数据库端执行,因此如果两个字段都声明为integer
,您肯定会获得integer
结果。在Django 1.11.7 中,你可以简单地将F()
表达式之一转换为decimal
,如下所示:
qs = (
MyModel.objects
.annotate(
res=ExpressionWrapper(
F('value1') * 1.0 / F('value2'),
output_field=FloatField(),
),
)
)
答案 3 :(得分:0)
在v1.10中,Django引入了一个Cast函数,这使(几乎)轻而易举–限定条件是您需要两次强制转换或需要将整个内容包装在ExpressionWrapper中以避免使用FieldError: Expression contains mixed types. You must set output_field.
q = MyModel.objects.annotate(
res=ExpressionWrapper(
(Cast('value1', FloatField()) / F('value2')),
output_field=FloatField()),
)
从功能上讲,这等效于将枚举数乘以1.0
,但是显式强制转换使您的意图比乘数更清晰。