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'))
这是做什么的:
- 正在对字段执行替换以删除逗号。
- 将该清理后的值传递给将清理后的字符串转换为浮点数的转换函数。
- 正在对结果求和。
如果 solarissmoke 的答案不是您想要的,您可以查看以下备选方案:
由于 aggregation/annotation needs real database fields,您可以放弃 aggregation/database 函数并循环遍历 python 中的查询集并将值转换为所需的数字类型(可能使用模型方法?)并对它们求和。
这确实带来了明显更差的性能。
您可以创建额外的数字模型字段,这些字段会在 save
之后自动填充(可能由 overriding the deffault save behaviour or using signals 完成)。然后在这些数字字段上使用聚合和 Sum
。您必须注意可能与原始 CharField
s 发生冲突,这会导致您的结果不正确(即错过更新,一些其他自定义行为)。
我有以下型号:
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'))
这是做什么的:
- 正在对字段执行替换以删除逗号。
- 将该清理后的值传递给将清理后的字符串转换为浮点数的转换函数。
- 正在对结果求和。
如果 solarissmoke 的答案不是您想要的,您可以查看以下备选方案:
由于 aggregation/annotation needs real database fields,您可以放弃 aggregation/database 函数并循环遍历 python 中的查询集并将值转换为所需的数字类型(可能使用模型方法?)并对它们求和。 这确实带来了明显更差的性能。
您可以创建额外的数字模型字段,这些字段会在
save
之后自动填充(可能由 overriding the deffault save behaviour or using signals 完成)。然后在这些数字字段上使用聚合和Sum
。您必须注意可能与原始CharField
s 发生冲突,这会导致您的结果不正确(即错过更新,一些其他自定义行为)。