Django 模型 - 无法使用千位逗号分隔符和小数点进行汇总

Django model - can't do aggregate sum with thousand comma separator and decimal points

我有以下型号:

class Example(models.Model):
    project_id = models.IntegerField(
        null=False, 
        blank=False, 
        default=0,
    )
    field1 = models.CharField(
        max_length=250,
        null=True, 
        blank=True,
    )
    field2 = models.CharField(
        max_length=250,
        null=True, 
        blank=True,
    )
    total = models.CharField(
        max_length=250,
        null=True, 
        blank=True,
    )

示例数据:

project_id field1 field2 total
1 1,323 4,234.55 5,557.55
2 1,000 2 1,002
3 1.23 3 4.23

total = field1 + field2

我想对所有 total 个值求和。

这是我试过的views.py:

context['total'] = Example.objects.filter(project_id=pid).aggregate(Sum('total'))

当前输出:

{'total': 10.23}

预期输出:

{'total': 6,563.78}

或者,如果这至少不可能:6563.78 以便我稍后可以格式化数字。

由于项目需要千位逗号分隔符和小数点,我无法更改或更改模型字段并使用 FloatField

如有任何帮助,我们将不胜感激

既然你说你不能改变字段本身的数据类型,你可以通过使用 Replace and Cast 数据库函数来实现(当然,这并不理想 - 最好是修复模型本身的数据类型)。

这应该可以工作 - 至少它可以在像 PostgreSQL 这样的 production-grade 数据库上工作(我不确定它是否可以在 SQLite 上工作 - 如果你在生产中使用它那么你真的有问题):

from django.db.models import FloatField, Value
from django.db.models.functions import Cast, Replace

context['total'] = Example.objects.annotate(
    cleaned_total=Replace('total', Value(','), Value(''))
).annotate(
    float_total=Cast('cleaned_total', FloatField())
).aggregate(Sum('float_total'))

这是做什么的:

  1. 正在对字段执行替换以删除逗号。
  2. 将该清理后的值传递给将清理后的字符串转换为浮点数的转换函数。
  3. 正在对结果求和。

如果 solarissmoke 的答案不是您想要的,您可以查看以下备选方案:

  1. 由于 aggregation/annotation needs real database fields,您可以放弃 aggregation/database 函数并循环遍历 python 中的查询集并将值转换为所需的数字类型(可能使用模型方法?)并对它们求和。 这确实带来了明显更差的性能。

  2. 您可以创建额外的数字模型字段,这些字段会在 save 之后自动填充(可能由 overriding the deffault save behaviour or using signals 完成)。然后在这些数字字段上使用聚合和 Sum。您必须注意可能与原始 CharFields 发生冲突,这会导致您的结果不正确(即错过更新,一些其他自定义行为)。