2012-12-11 49 views

回答

5

您想使用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來解決。

+0

謝謝!我將仔細看看MultiWidget鏈接。關於timedelta:與我的IntegerField存儲分鐘相比,您如何描述使用timedelta的性能?我正在構建一個訓練日誌,其中會有大量的總結。 – LordNelson

+1

我不認爲這應該是一個問題(int計算的執行速度大概是我想的速度的兩倍,但我懷疑你確實需要優化這一點 - 它不太可能成爲應用程序的瓶頸)。 –

+0

@LordNelson我已經添加了一個基本字段的代碼,使用帶有小時,分鐘,秒部件的浮點數。它應該是相當簡單的調整這個小時和秒或整數基地領域。 –

相關問題