Пользовательское десятичное поле Django - лучший способ автоматического преобразования с плавающей запятой в двойное?

У меня мало мест в базе данных, когда я использую DecimalField. К сожалению, я должен обрабатывать как двойные, так и плавающие данные в качестве входных данных - и есть моя проблема.

Я хочу сделать жестокое отсечение значения (после второго десятичного знака), а не математический раунд. Я сохраняю вычисленное значение, цель которого трудно превысить (если у меня есть значение 49,9832100000032131, оно все равно меньше 50, поэтому я не буду округлять его). Но, как я уже сказал, я хочу сохранить его как 48.98 в базе данных (с двумя десятичными разрядами), сохраняя память и достаточное представление.

Мое первое решение - использовать настраиваемое поле django, что-то вроде этого:

class DecimalFixedField(models.DecimalField):

def __init__(self, *args, **kwargs):
    kwargs['value'] = "{0:.2f}".format( kwargs['value'] )            
    # or ? self.value = "{0:.2f}".format( kwargs['value'] )
    super(DecimalFixedField, self).__init__(*args, **kwargs)

Конечно, я должен жестко кодировать decimal_places = 2 в kwargs или использовать его в коде, а не в значении 2, но... как насчет остальных? У вас есть подсказка, лучшая идея?

Что важно - я не хочу писать "{0:.2f}". Format (...) во многих местах кода! Я хотел сделать это в методологии ООП, потому что я использую DecimalField во многих моделях... и сделать эту предварительную обработку выглядит как хорошее решение. Есть мысли, как это будет правильно реализовано?

2 ответа

Подумав и попробовав, я сделал что-то вроде этого:

class DecimalFixedField(models.DecimalField):

    def pre_save(self, model_instance, add):

        # reading value
        value_field = getattr(model_instance, self.attname)

        # casting to decimal if the value is not a decimal (float for example)
        if not isinstance(value_field, decimal.Decimal):
            value_field = decimal.Decimal(str(value_field))

        # there you can cut off the value
        quantized_value = value_field.quantize(decimal.Decimal(str(0.1**self.decimal_places)), rounding=decimal.ROUND_DOWN)

        # saving value
        setattr(model_instance, self.attname, quantized_value)
        return quantized_value

может быть, это будет полезно для кого-то:)

Попробуйте использовать это:

from decimal import Decimal

my_value = Decimal(value) 
Другие вопросы по тегам