在 Django rest 中将整数格式化为注释内的百分比
format count integer into percentage inside annotate in Djnago rest
我必须在 DRF 的 API 调用中发送计数百分比。我已经使用注释计算了计数并附加到查询集。但实际上我需要的是百分比而不是计数。
TYPES = ((1,'cold'),
(2,'humid'),
(3,'hot'))
from django.db.models import Q,Count
class Destinations(models.Model):
continent = models.CharField()
/............/
class Packages(models.Model):
location = models.Foreignkey(Destination,on_delete=models.CASCADE,related_name='packages')
place_type = models.CharField(
max_length=1,
choices=TYPES,
default=""
我的看法:
我在 modelviewset 中使用了列表函数,像这样:
Destiantion = Destination.objects.all().annotate(total_packages=Count('packages'),
cold_count=Count('packages',filter=Q(packages__place_type=1)),
humid_count=Count('packages',filter=Q(packages__place_type=2)),
hot_count =Count('packages',filter=Q(packages__place_type=3)))
在这里,我得到的响应是属性中包类型的计数,但我想要的是包类型的百分比,如 25%,方法是 cold_count*100/total_packages
,但不能在注释中使用它。
有一个 count() 方法可能有用,但如果我使用它,我必须进行 4 个单独的查询,并且可能为此编写另一个 API。所以我必须使用注释。但是怎么办呢??
你应该试试
from django.db.models.functions import Coalesce
Destination.objects.all().annotate(
total_packages=Count('packages'),
cold_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=1)) / Count('packages'), 0),
humid_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=2)) / Count('packages'), 0),
hot_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=3)) / Count('packages'), 0),
)
此外,如果你需要处理 Count('packages')=0
时的情况,你需要这样的东西:
from django.db.models.functions import Coalesce
Destination.objects.all().annotate(
total_packages=Count('packages'),
cold_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=1)) / Count('packages'), 'total_packages'), 0),
humid_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=2)) / Count('packages'), 'total_packages'), 0),
hot_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=3)) / Count('packages'), 'total_packages'), 0),
)
其中 div_zero
如下:
from django.db.models import Case, Value, FloatField
from django.db.models.expressions import When
INFINITY = 1000000000000
def div_zero(result, divisor):
return Case(
When(**{
divisor: 0,
'then': Value(INFINITY, FloatField()),
}),
default=result,
output_field=FloatField(),
)
我必须在 DRF 的 API 调用中发送计数百分比。我已经使用注释计算了计数并附加到查询集。但实际上我需要的是百分比而不是计数。
TYPES = ((1,'cold'),
(2,'humid'),
(3,'hot'))
from django.db.models import Q,Count
class Destinations(models.Model):
continent = models.CharField()
/............/
class Packages(models.Model):
location = models.Foreignkey(Destination,on_delete=models.CASCADE,related_name='packages')
place_type = models.CharField(
max_length=1,
choices=TYPES,
default=""
我的看法:
我在 modelviewset 中使用了列表函数,像这样:
Destiantion = Destination.objects.all().annotate(total_packages=Count('packages'),
cold_count=Count('packages',filter=Q(packages__place_type=1)),
humid_count=Count('packages',filter=Q(packages__place_type=2)),
hot_count =Count('packages',filter=Q(packages__place_type=3)))
在这里,我得到的响应是属性中包类型的计数,但我想要的是包类型的百分比,如 25%,方法是 cold_count*100/total_packages
,但不能在注释中使用它。
有一个 count() 方法可能有用,但如果我使用它,我必须进行 4 个单独的查询,并且可能为此编写另一个 API。所以我必须使用注释。但是怎么办呢??
你应该试试
from django.db.models.functions import Coalesce
Destination.objects.all().annotate(
total_packages=Count('packages'),
cold_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=1)) / Count('packages'), 0),
humid_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=2)) / Count('packages'), 0),
hot_count_percent=Coalesce(100.0 * Count('packages',filter=Q(packages__place_type=3)) / Count('packages'), 0),
)
此外,如果你需要处理 Count('packages')=0
时的情况,你需要这样的东西:
from django.db.models.functions import Coalesce
Destination.objects.all().annotate(
total_packages=Count('packages'),
cold_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=1)) / Count('packages'), 'total_packages'), 0),
humid_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=2)) / Count('packages'), 'total_packages'), 0),
hot_count_percent=Coalesce(div_zero(100.0 * Count('packages',filter=Q(packages__place_type=3)) / Count('packages'), 'total_packages'), 0),
)
其中 div_zero
如下:
from django.db.models import Case, Value, FloatField
from django.db.models.expressions import When
INFINITY = 1000000000000
def div_zero(result, divisor):
return Case(
When(**{
divisor: 0,
'then': Value(INFINITY, FloatField()),
}),
default=result,
output_field=FloatField(),
)