我尝试在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,而不是除以100。
有什么建议吗?
我试过this解决方案,但是它重复了100次这个值。在我纠正这个问题后,它也有同样的问题。
我用的是Python 3.5
4条答案
按热度按时间xxe27gdn1#
我找到了解决方案。我必须检查传入的值是否是字符串。如果是,我就不乘以100,因为它来自表单。见下图:
ee7vknir2#
有一个简单的替代方法,你可以使用
MaxValueValidator
和MinValueValidator
。以下是您可以执行此操作的方法:
nnsrf1az3#
我的解决方案
根据@elachere的回答和Django文档,这是我正在使用的代码:
为什么接受的答案对我无效
我遇到了类似的问题,但我希望我的
PercentageField
是基于DecimalField
而不是FloatField
,在货币方面与recommendations一致。在这种情况下,目前公认的答案对我在Django 4.0中不起作用,原因有2:to_python
被调用了两次,一次是由clean
方法调用(如the documentation中所述),另一次是由get_db_prep_save
调用(在文档中提到)。事实上,(在Django源代码中)DecimalField
和FloatField
在这一点上是不同的。prepare_value
根本不会运行。覆盖
django.db.models.fields.Field.pre_save
可能是一种替代方法,但以下代码仍然存在问题:刚刚保存的当前示例的属性太小了100倍(由于pre_save
中的除法),如果需要进一步使用它,则必须调用instance.refresh_from_db()
。kxxlusnw4#
从文档中可以看出,
to_python()
应该用于处理复杂数据类型的情况,以帮助您与数据库交互。我认为更准确的方法是覆盖pre_save()
Field
方法。从文档中可以看出:pre_save(模型示例,添加)
在get_db_prep_save()之前调用的方法,用于在保存值之前准备值(例如,用于DateField.auto_now)。
最后,它看起来像这样:
我的情况有点不同,我想要一个比率而不是一个百分比,所以我只允许0到100之间的值,这就是为什么我需要一个验证器,但想法是在这里。