フィールドをレンダリングする方法をカスタマイズするには、ウィジェットも定義する必要があります。
ウィジェットのコードは、ウィジェットの影響を受けていることに注意してください。一貫性を維持するためにdjangoのソースコードからの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になることに注意してください。これは、フロートの使用によって引き起こされる精度の低下によるものです。ある精度を失いたくない場合は、データ型を変更することができます。
_format_value()の%1dは10,11,12のような時間を切り捨てませんか? –
"1"は 'width'パラメータで、パディングにのみ使用され、切り捨てには使用されません。つまり、左に文字が追加され、削除されることはありません。 %演算子はsprintf(http://en.wikipedia.org/wiki/Printf#printf_format_placeholders)のように動作します。 このように数字の整数部分を切り捨てることはできません。精度パラメータ( "%.2f"%0.123 == "0.12")を使用して小数部分のみを切り捨てることができます。 精度パラメータを文字列形式で使用して切り捨てることができます。 "%.1s"%123 == "1" – vincent
ところで、バグは導入されませんが、この '%1d'は役に立たない任意の数値は常に整数部分の文字を生成します:-)私は "%2d:%2d"で始まり、時間部分には1つの文字のみが必要であると考えたので、これを書いています。 – vincent