我存储的持续时间在一个IntegerField分钟。 在我的前端形式(标准格式),我想输入分成几分钟一个字段和小时一个字段。 我也希望能够使用InLineFormset。 这可以在一个不错的方式进行? 我可以使用JavaScript,但并不像seeml一个很好的解决方案给我,是吗?
Answer 1:
你想用一个MultiWidget 。 我建议你覆盖领域本身。 看一看的文档创建自定义字段 。
如果可以的话,它可能是值得存储您的数据表示浮点蟒蛇timedelta 。 您可能需要一些自定义方法添加到您的领域。 如果你想要做的任何计算与现场使用timedelta将是有益的。
你可能想要做的阅读了一下表单验证了。
我测试了以下时,分,秒multiwidget上的Django 1.4基于浮动的自定义字段 -
from datetime import timedelta
from django import forms
from django.db import models
from django.core import exceptions, validators
def validate_timedelta(value):
if not isinstance(value, timedelta):
raise exceptions.ValidationError('A valid time period is required')
class SplitHoursMinsWidget(forms.widgets.MultiWidget):
def __init__(self, *args, **kwargs):
widgets = (
forms.TextInput(),
forms.TextInput(),
forms.TextInput(),
)
super(SplitHoursMinsWidget, self).__init__(widgets, *args, **kwargs)
def decompress(self, value):
if value:
return [value.seconds // 3600, (value.seconds // 60) % 60,
value.seconds % 60]
return [None, None, None]
def format_output(self, rendered_widgets):
return ("HH:MM:SS " + rendered_widgets[0] + ":" + rendered_widgets[1] +
":" + rendered_widgets[2])
def value_from_datadict(self, data, files, name):
hours_mins_secs = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)]
try:
time_delta = (timedelta(hours=float(hours_mins_secs[0])) +
timedelta(minutes=float(hours_mins_secs[1])) +
timedelta(seconds=float(hours_mins_secs[2])))
except ValueError:
return None
else:
return time_delta
class TimeDeltaFormField(forms.Field):
widget = SplitHoursMinsWidget
class TimeDeltaField(models.Field):
__metaclass__ = models.SubfieldBase
description = "Field to hold a python timedelta object"
default_validators = [validate_timedelta, ]
def to_python(self, value):
if value in validators.EMPTY_VALUES or isinstance(value, timedelta):
return value
try:
return timedelta(seconds=float(value))
except:
raise exceptions.ValidationError('A valid time period is required')
def get_prep_value(self, value):
return float(value.days * 86400 + value.seconds)
def get_internal_type(self):
return 'FloatField'
def formfield(self, **kwargs):
defaults = {'form_class': TimeDeltaFormField}
defaults.update(kwargs)
return super(TimeDeltaField, self).formfield(**defaults)
值得一提的是,这并不提供任何有用的输入电平验证(有可能同时在分和秒输入元素进入60)。 也许这可以使用JavaScript最佳解决。
文章来源: Django custom widget to split an IntegerField into hours and seconds fields in a Model Form