Django djsonfield Decimal 在表达式中存储为字符串
Django djsonfield Decimal stored as string in expressions
我有一个包含一些财务数据的 JSONField。我不能将它存储为浮点数,因为我需要精度,所以我将它存储为字符串。
我的模型是这样的
class Finance(models.Model)
bill_data = JSONField(
verbose_name=_("Bill data"),
default=dict,
blank=True,
)
那我存
bill_data = dict(paid=str(some_decimal_amount))
Finance.objects.create(bill_data=bill_data)
我尝试使用Cast
将其转换回十进制,因为我需要使用表达式,
Finance.objects.all().annotate(paid=Cast('bill_data__paid', DecimalField()))
我收到一个错误
return self.cursor.execute(sql, params)
django.db.utils.DataError: invalid input syntax for integer: "none"
LINE 1: ...der"."bill_data", ("myapp_finance"."bill_data")::numeric(No...
有谁知道如何在表达式中使用 JSONField
中的 str
或如何正确处理 JSONField
中的 Decimal
?
所以今天我为此苦苦挣扎。在帮助下,我们设法使其正常工作。
from django.db.models.functions import Cast
from django.db.models.fields.json import KeyTextTransform
from django.db.models import JSONField, DecimalField
from django.db import models
class Finance(models.Model):
bill_data = JSONField(
verbose_name="Bill data",
default=dict,
blank=True,
)
好的,所以首先我假设 bill_data__paid 在任何地方都不是 Null。如果是,你应该先做一个:
Finance.objects.filter(bill_data__paid__isnull=False)
确保您没有投射任何 Null 字段。
好的,那我们试试你做的:
Finance.objects.annotate(
paid=Cast("bill_data__paid", output_field=DecimalField()),
)
但是我们得到一个错误,大致如下:
invalid input syntax for type integer: "none" LINE 1: #
...("myapp_finance"."bill_data" -> 'paid') AS numeric(No......
好吧,那不是很好。那我们现在能做什么呢?好吧,也许我们需要指定小数字段的小数位数和最大位数,你说得对。
Finance.objects.annotate(
paid=Cast("bill_data__paid", output_field=DecimalField(max_digits=6, decimal_places=2)),
)
但这行得通吗?可悲的是没有。我们现在收到错误
cannot cast jsonb string to type numeric
嗯,好的。不是很好,但至少这是一个不同的错误。问题是我们有一个 jsonb 字符串。让我们把它变成一个文本文本字符串(因为缺少更好的描述)
Finance.objects.annotate(
paid=Cast(KeyTextTransform("paid", "bill_data"), output_field=DecimalField(max_digits=6, decimal_places=2))
)
现在,它将起作用。
因此我们将 jsonb 字符串转换为文本,然后将其转换为十进制(您必须指定小数位数和最大位数)。
结束:)
我有一个包含一些财务数据的 JSONField。我不能将它存储为浮点数,因为我需要精度,所以我将它存储为字符串。
我的模型是这样的
class Finance(models.Model)
bill_data = JSONField(
verbose_name=_("Bill data"),
default=dict,
blank=True,
)
那我存
bill_data = dict(paid=str(some_decimal_amount))
Finance.objects.create(bill_data=bill_data)
我尝试使用Cast
将其转换回十进制,因为我需要使用表达式,
Finance.objects.all().annotate(paid=Cast('bill_data__paid', DecimalField()))
我收到一个错误
return self.cursor.execute(sql, params)
django.db.utils.DataError: invalid input syntax for integer: "none"
LINE 1: ...der"."bill_data", ("myapp_finance"."bill_data")::numeric(No...
有谁知道如何在表达式中使用 JSONField
中的 str
或如何正确处理 JSONField
中的 Decimal
?
所以今天我为此苦苦挣扎。在帮助下,我们设法使其正常工作。
from django.db.models.functions import Cast
from django.db.models.fields.json import KeyTextTransform
from django.db.models import JSONField, DecimalField
from django.db import models
class Finance(models.Model):
bill_data = JSONField(
verbose_name="Bill data",
default=dict,
blank=True,
)
好的,所以首先我假设 bill_data__paid 在任何地方都不是 Null。如果是,你应该先做一个:
Finance.objects.filter(bill_data__paid__isnull=False)
确保您没有投射任何 Null 字段。
好的,那我们试试你做的:
Finance.objects.annotate(
paid=Cast("bill_data__paid", output_field=DecimalField()),
)
但是我们得到一个错误,大致如下:
invalid input syntax for type integer: "none" LINE 1: # ...("myapp_finance"."bill_data" -> 'paid') AS numeric(No......
好吧,那不是很好。那我们现在能做什么呢?好吧,也许我们需要指定小数字段的小数位数和最大位数,你说得对。
Finance.objects.annotate(
paid=Cast("bill_data__paid", output_field=DecimalField(max_digits=6, decimal_places=2)),
)
但这行得通吗?可悲的是没有。我们现在收到错误
cannot cast jsonb string to type numeric
嗯,好的。不是很好,但至少这是一个不同的错误。问题是我们有一个 jsonb 字符串。让我们把它变成一个文本文本字符串(因为缺少更好的描述)
Finance.objects.annotate(
paid=Cast(KeyTextTransform("paid", "bill_data"), output_field=DecimalField(max_digits=6, decimal_places=2))
)
现在,它将起作用。
因此我们将 jsonb 字符串转换为文本,然后将其转换为十进制(您必须指定小数位数和最大位数)。
结束:)