我已经为百分比(Djangosnippet #1914的修改版本)实现了自定义表单字段。我这样做就像世界上其他人一样:将0.25的值显示为25%。为了实现这一点,我们需要在显示之前将值乘以100,并在保存时将其除以100(见下文)。
保存部分(clean
)工作正常,但问题在于显示值(render
或更确切地说prepare_value
)。传递给prepare_value
的值有不同类型。它可能是你的默认值(我的是0)所以它将是 int 但它也可能是 Decimal (大部分时间)因为毕竟它是 DecimalField
当表单抛出错误并且需要重新显示值时,会出现问题。在这种情况下,表单值将传递给它 - 这是一个 unicode 。所以我们不需要将值乘以100,因为之前已经完成了(更确切地说:因为值可能与 Decimal 不同 - 即 int 或 unicode - 我们需要在它不是 Decimal 时将它相乘。即 - DecimalField )。正如您所看到的,我使用isinstance
进行了一次难看的解决方法。
我开始认为我真的不明白这里发生了什么,我不知道如何正确地解决这个问题。有什么建议吗?
class PercentInput(TextInput):
def render(self, name, value, attrs=None):
from django.utils.safestring import mark_safe
return super(PercentInput, self).render(name, value, attrs) + \
mark_safe(u' %')
class PercentField(DecimalField):
widget = PercentInput(attrs={'size': 4, 'maxlength': 5})
default_error_messages = {
'positive': _(u'Must be a positive number.'),
}
def prepare_value(self, value):
if isinstance(value, Decimal):
value *= 100
return super(PercentField, self).prepare_value(value)
def clean(self, value):
value = super(PercentField, self).clean(value)
if value is None:
return None
if value < 0:
raise ValidationError(self.error_messages['positive'])
return Decimal('%.4f' % (value / 100))
答案 0 :(得分:0)
您可以考虑将MultiValueField与MultiWidget结合使用。给你的优点是MultiValueField有一个compress方法,你可以利用它来输入你的输入并将其转换为十进制形式,MultiWidget有一个解压缩方法来取小数并将其转换为字符串并显示它你想怎么做。
我写了一个Feet and Inches widget,将小数转换为英尺,英寸和小数英寸(10英尺3 1/2英寸,存储在数据库中为123.5),几乎可以满足您的需要。希望有所帮助你出去了!