英文:
Django .first() method cuts first digit from a Decimal
问题
我在使用QuerySet
上的.first()
方法时遇到了非常奇怪的行为。在调用该方法后,十进制值的第一个数字被删除。
模型:
class Distributions(models.Model):
distribution_id = models.AutoField(primary_key=True)
months_duration = models.IntegerField(blank=True, null=True)
month = models.IntegerField(blank=True, null=True)
activity_date = models.DateField(blank=True, null true)
value_in_percentage = models.DecimalField(
max_digits=8, decimal_places=4, blank=True, null=True
)
value_in_units = models.DecimalField(
max_digits=16, decimal_places=4, blank=True, null=True
)
distribution_type = models.ForeignKey(
DistributionType, on_delete=models.DO_NOTHING, blank=True, null=True
)
area = models.ForeignKey(Area, on_delete=models.DO_NOTHING, blank=True, null=True)
is_active = models.BooleanField(blank=True, null=True)
月度值:
data = Distributions.objects.all()
monthly_values = data.values("distribution_type_id", "activity_date").annotate(tsum=Sum("value_in_units"))
代码:
def _get_month_value(self, id: int, month_values: QuerySet) -> int:
print("----------")
print(month_values)
print(month_values.filter(id=id).values('tsum'))
print(month_values.filter(id=id).values('tsum').first())
print(month_values.filter(id=id).values('tsum')[0])
输出如下:
<QuerySet [{'id': 1, 'tsum': Decimal('519')}, {'id': 3, 'tsum': Decimal('1019')},
{'id': 5, 'tsum': Decimal('0')}, {'id': 9, 'tsum': Decimal('0')}]>
<QuerySet [{'tsum': Decimal('519')}]>
{'tsum': Decimal('19')}
{'tsum': Decimal('519')}
如您所见,对于id
为1的情况,原始值为519,但在调用first()
方法后变成了19。如果我手动使用[0]
调用QuerySet的第一个项目,则不会发生这种情况。
有什么可能引起这个问题的想法吗?
提前感谢
英文:
I am seeing really strange behavior when using .first()
method on a QuerySet
. After calling the method, first digit from a Decimal value gets cut.
Models:
class Distributions(models.Model):
distribution_id = models.AutoField(primary_key=True)
months_duration = models.IntegerField(blank=True, null=True)
month = models.IntegerField(blank=True, null=True)
activity_date = models.DateField(blank=True, null=True)
value_in_percentage = models.DecimalField(
max_digits=8, decimal_places=4, blank=True, null=True
)
value_in_units = models.DecimalField(
max_digits=16, decimal_places=4, blank=True, null=True
)
distribution_type = models.ForeignKey(
DistributionType, on_delete=models.DO_NOTHING, blank=True, null=True
)
area = models.ForeignKey(Area, on_delete=models.DO_NOTHING, blank=True, null=True)
is_active = models.BooleanField(blank=True, null=True)
Monthly values:
data = Distributions.objects.all()
monthly_values = data.values("distribution_type_id", "activity_date").annotate(tsum=Sum("value_in_units"))
Code:
def _get_month_value(self, id: int, month_values: QuerySet) -> int:
print("----------")
print(month_values)
print(month_values.filter(id=id).values('tsum'))
print(month_values.filter(id=id).values('tsum').first())
print(month_values.filter(id=id).values('tsum')[0])
The outputs are as follows:
<QuerySet [{'id': 1, 'tsum': Decimal('519')}, {'id': 3, 'tsum': Decimal('1019')},
{'id': 5, 'tsum': Decimal('0')}, {'id': 9, 'tsum': Decimal('0')}]>
<QuerySet [{'tsum': Decimal('519')}]>
{'tsum': Decimal('19')}
{'tsum': Decimal('519')}
As you can see for id
1 the original value is 519 but after I call the first()
method it gets turned into a 19. This does not happend if I manually call the first item in QueySet using [0]
.
Any idea what might be causing this issue?
Thanks in advance
答案1
得分: 1
问题在于函数 first
在 SQL 查询中使用了 FIRST、TOP 或 LIMIT,并且在 SELECT 语句中使用了 SUM。
Django 仅在您需要该值时执行查询,因此 first()
执行整个查询并筛选用于求和的元素。
您可以使用 print(queryset.query)
查看 SQL 查询。
在您的代码中,SQL 查询是 SELECT CAST(SUM("app_distributions"."value_in_units") AS NUMERIC) AS "tsum" FROM "app_distributions" WHERE "app_distributions"."id" = N GROUP BY "app_distributions"."distribution_type_id" "app_distributions"."activity_date"
(或类似的查询),当您使用 first()
时,Django 会添加更多的 SQL 并仅获取第一条记录,然后仅对此记录进行求和。
英文:
the problem is that the function first
use FIRST, TOP, or LIMIT in SQL query and SUM in the select.
Django executes the query only when you need the value, so the first()
executes all the query and filters elements that the sum uses.
You can see de sql query with print(queryset.query)
.
In your code, the sql is SELECT CAST(SUM("app_distributions"."value_in_units") AS NUMERIC) AS "tsum" FROM "app_distributions" WHERE "app_distributions"."id" = N GROUP BY "app_distributions"."distribution_type_id" "app_distributions"."activity_date"
(or similar), and when you use first()
, django add more sql and only get the first record and sum only this record.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论