我有一个名为HourField的自定义字段,可让您输入“1:30”代表一个半小时。对于模型中的FloatField,clean()
方法将其转换为1.5。一切正常。现在我遇到了一个问题,当我想创建一个formset时,该字段被渲染为“1.5”而不是“1:30”,这就是我想要的。
是否有某种类似于clean()
的方法,但反过来呢?
编辑:使用其他类型的存储方法是不可能的。我有一些其他自定义字段存储为一种类型的对象,但由用户输入为字符串。我使用上面的例子,因为它是最直接的。
答案 0 :(得分:3)
要自定义字段呈现的方式,您还需要定义窗口小部件。
以下代码显示了django中小部件的一些职责:
请注意,小部件的代码的灵感来自django源代码中的widgets.TimeInput,这有助于保持一致。
from django import forms
from django.forms import widgets
from django.forms.util import ValidationError
class HourWidget(widgets.TextInput):
def _format_value(self, value):
if isinstance(value, float) or isinstance(value, int):
import math
hours = math.floor(value)
minutes = (value - hours) * 60
value = "%d:%02d" % (hours, minutes)
return value
def render(self, name, value, attrs=None):
value = self._format_value(value)
return super(HourWidget, self).render(name, value, attrs)
def _has_changed(self, initial, data):
return super(HourWidget, self)._has_changed(self._format_value(initial), data)
class HourField(forms.Field):
widget = HourWidget
def clean(self, value):
super(HourField, self).clean(value)
import re
match = re.match("^([0-9]{1,2}):([0-9]{2})$", value)
if not match:
raise ValidationError("Please enter a valid hour ( ex: 12:34 )")
groups = match.groups()
hour = float(groups[0])
minutes = float(groups[1])
if minutes >= 60:
raise ValidationError("Invalid value for minutes")
return hour + minutes/60
请注意1:20变为1:19,这是由于使用浮子造成的精度损失。如果您不想丢失一些精度,可能需要更改数据类型。
答案 1 :(得分:1)
如何在表单字段中显示数据是窗口小部件的责任。看起来您需要定义一个自定义窗口小部件,该窗口小部件实现一个render()
方法,该方法接受十进制字段值并根据需要输出它。
不幸的是,似乎没有关于创建自定义窗口小部件的任何文档,但您可以查看django.forms.extras.widgets
中的代码以获取如何执行此操作的示例。
答案 2 :(得分:1)
from django.forms.widgets import TextInput
class TimeInput(TextInput):
def _format_value(self, value):
"""Convert float to time"""
if not value:
return ''
fraction, integer = math.modf(value)
minutes = 0 if fraction == 0 else .6 / fraction
return "%d:%02d" % (int(integer), int(minutes))
def render(self, name, value, attrs=None):
value = self._format_value(value)
return super(TimeInput, self).render(name, value, attrs)
答案 3 :(得分:0)
我认为您可能想要试用date template tag或者可能想要创建自己的模板标记。这是创可贴 - 但真正的问题是你应该使用datetime模块将时间存储在Python中。这样可以保证格式化。