Django-注释并将加密的TextField强制转换为FloatField的小数点后2位

时间:2018-09-19 09:58:00

标签: django postgresql django-models django-postgresql pgcrypto

我正在使用Django pgcrypto fields加密模型中的金额值 Invoice如下:

from pgcrypto import fields

class Invoice(models.Model):
    # Some other fields
    amount_usd = fields.TextPGPSymmetricKeyField(default='')

    objects = InvoicePGPManager()  # Manager used for PGP Fields

我使用的是TextPGPSymmetricKeyField,因为我必须将值存储为浮点数,而django-pgcrypto-fields没有与FloatField等效的内容。

现在,我需要通过API传递此amount_usd值,并且必须将小数位限制在两个位置。

我尝试使用以下内容:

Invoice.objects.all().values('amount_usd').annotate(
    amount_to_float=Cast('amount_usd', FloatField())
)

但这会导致错误,因为无法将字节(加密数据)转换为浮点数。

我也尝试使用它:

from django.db.models import Func

class Round(Func):
    function = 'ROUND'
    template='%(function)s(%(expressions)s, 2)'


Invoice.objects.all().annotate(PGPSymmetricKeyAggregate(
            'amount_usd')).annotate(amount=Cast(
            'amount_usd__decrypted', FloatField())).annotate(
            amount_final = Round('amount'))

我收到以下错误:

django.db.utils.ProgrammingError: function round(double precision, integer) does not exist
LINE 1: ...sd, 'ultrasecret')::double precision AS "amount", ROUND(pgp_...
                                                         ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

是否可以将加密字段转换为最多2个小数位的FloatField?

1 个答案:

答案 0 :(得分:1)

您的错误说:double precision AS "amount" 这是因为您要将amount_usd转换为FloatField,从而在SQL中转换为双精度。

尝试使用带有参数的DecimalField(在SQL中转换为数字)。

Invoices.objects.all().annotate(amount=Cast(
    PGPSymmetricKeyAggregate('amount_usd'),
    DecimalField(max_digits=20, decimal_places=2)))

在此处查看文档:{​​{3}}