tim*_*tim 9 python django django-queryset
我有这个代码:
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)
Run Code Online (Sandbox Code Playgroud)
所以,输出将是:
5 10 0.0
1 2 0.0
Run Code Online (Sandbox Code Playgroud)
但是我需要
5 10 0.5
1 2 0.5
Run Code Online (Sandbox Code Playgroud)
Wy F()将结果四舍五入?怎么不这样做?
谢谢!
joa*_*nbm 14
只需使用F()对乘法的支持即可将一个因子转换为十进制数.
结合表达式然后看起来像:
from decimal import Decimal
q = MyModel.objects.order_by('-value1').annotate(
res=ExpressionWrapper(
(F('value1') * Decimal('1.0') / F('value2')),
output_field=FloatField()),
)
Run Code Online (Sandbox Code Playgroud)
我发现这种更优雅的方式然后在value1字段上写入原始SQL CAST然后进行除法.
不幸的是,ORMF('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(),
),
)
)
Run Code Online (Sandbox Code Playgroud)
您期望的结果真的很容易通过原始查询来实现,而且,我的意思是使用纯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)
Run Code Online (Sandbox Code Playgroud)
您不会觉得这很优雅,但它同时适用于Mysql和Postgresql。
提供一些背景。四舍五入是通过数据库进行整数除法完成的,因为您拥有的字段是整数。如果要十进制除法,则需要将它们转换为小数。不幸的是,使用Django进行铸造并不是一件容易的事。
Postgresql有一个非常优雅的方法来进行浮动。value1 :: float,但这不能从Django内部使用(至少据我所知)
在 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()),
)
Run Code Online (Sandbox Code Playgroud)
这在功能上等同于将枚举数乘以1.0,但与乘以数字相比,显式强制转换使您的意图更清晰。
| 归档时间: |
|
| 查看次数: |
2187 次 |
| 最近记录: |