Django百分比字段

时间:2016-04-07 13:31:56

标签: python django

我试图在Django中创建一个百分比字段,用户只需填写40%的40%。输入框右侧会有一个百分号,这样他们就知道应填写一个百分比。 0.4必须存储在DB中。到目前为止,我已尝试过以下方法:

class PercentageField(fields.FloatField):
    widget = fields.TextInput(attrs={"class": "percentInput"})

    def to_python(self, value):
        val = super(PercentageField, self).to_python(value)
        if is_number(val):
            return val/100
        return val

    def prepare_value(self, value):
        val = super(PercentageField, self).prepare_value(value)
        if is_number(val):
            return str((float(val)*100))
        return val

def is_number(s):
    if s is None:
        return False
    try:
        float(s)
        return True
    except ValueError:
        return False

它有效,但问题是,当我发布无效数据并再次呈现表单时,它会将40显示为4000.换句话说,它再次将数字乘以100而不将其除以。

我有什么建议可以解决它吗?

我已尝试过this解决方案,但它会重复该值100次。在我纠正之后,它也有同样的问题。

我使用的是Python3.5

2 个答案:

答案 0 :(得分:1)

我找到了解决方案。我必须检查传入的值是否为字符串。如果是,我不会乘以100,因为它来自表格。见下文:

class PercentageField(fields.FloatField):
    widget = fields.TextInput(attrs={"class": "percentInput"})

    def to_python(self, value):
        val = super(PercentageField, self).to_python(value)
        if is_number(val):
            return val/100
        return val

    def prepare_value(self, value):
        val = super(PercentageField, self).prepare_value(value)
        if is_number(val) and not isinstance(val, str):
            return str((float(val)*100))
        return val

答案 1 :(得分:0)

在文档中,to_python()应该用于处理复杂数据类型的情况,以帮助您与数据库进行交互。我认为一种更准确的方法是重写pre_save() Field方法。从文档中:

pre_save(model_instance,添加)

在get_db_prep_save()之前调用的方法,以在保存之前准备值(例如,对于DateField.auto_now)。

最后,它看起来像这样:

def validate_ratio(value):
    try:
        if not (0 <= value <= 100):
            raise ValidationError(
                f'{value} must be between 0 and 100', params={'value': value}
            )
    except TypeError:
        raise ValidationError(
            f'{value} must be a number', params={'value': value}
        )


class RatioField(FloatField):
    description = 'A ratio field to represent a percentage value as a float'

    def __init__(self, *args, **kwargs):
        kwargs['validators'] = [validate_ratio]
        super().__init__(*args, **kwargs)

    def pre_save(self, model_instance, add):
        value = getattr(model_instance, self.attname)
        if value > 1:
            value /= 100
        setattr(model_instance, self.attname, value)
        return value

我的情况有点不同,我想要一个比率而不是一个百分比,所以我只允许0到100之间的值,这就是为什么我需要一个验证器,但是想法就在这里。