2
我將時間持續時間存儲爲IntegerField中的分鐘數。在我的前端表單(Model Form)中,我想將輸入分爲一個字段分鐘和一個字段幾個小時。我也希望能夠使用InLineFormset。這可以以很好的方式完成嗎?我可以使用JavaScript,但這並不像我看到一個好的解決方案,或者是它?Django自定義小部件將整數字段拆分爲模型表單中的小時和秒字段
我將時間持續時間存儲爲IntegerField中的分鐘數。在我的前端表單(Model Form)中,我想將輸入分爲一個字段分鐘和一個字段幾個小時。我也希望能夠使用InLineFormset。這可以以很好的方式完成嗎?我可以使用JavaScript,但這並不像我看到一個好的解決方案,或者是它?Django自定義小部件將整數字段拆分爲模型表單中的小時和秒字段
您想使用MultiWidget。我建議你重寫該字段本身。看看docs for creating custom fields。
如果可以,可能值得將數據存儲爲表示python timedelta的浮點數。您可能需要將一些自定義方法添加到您的字段中。如果你想對你的領域進行任何計算,使用timedelta會很有用。
您可能還想在form validation上閱讀一下。
我已經測試了以下時,分,秒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來解決。
謝謝!我將仔細看看MultiWidget鏈接。關於timedelta:與我的IntegerField存儲分鐘相比,您如何描述使用timedelta的性能?我正在構建一個訓練日誌,其中會有大量的總結。 – LordNelson
我不認爲這應該是一個問題(int計算的執行速度大概是我想的速度的兩倍,但我懷疑你確實需要優化這一點 - 它不太可能成爲應用程序的瓶頸)。 –
@LordNelson我已經添加了一個基本字段的代碼,使用帶有小時,分鐘,秒部件的浮點數。它應該是相當簡單的調整這個小時和秒或整數基地領域。 –