2009-02-12 60 views
3

作爲一個練習,我試圖創建一個24小時制的自定義Django小部件。該小部件將是一個MultiWidget - 每個字段的選擇框。自定義django小部件 - 解壓縮()arg沒有填充

我想跟隨在線文檔(有點稀疏),看着專業Django書,但我似乎無法弄清楚。我在正確的軌道上嗎?我可以從表單中保存數據,但是當我預先填充表單時,表單沒有以前的值。

看來問題是,解壓縮()方法的'值'參數總是空的,所以我沒有任何解釋。

from django.forms import widgets 

import datetime 

class MilitaryTimeWidget(widgets.MultiWidget): 
    """ 
    A widget that displays 24 hours time selection. 
    """ 
    def __init__(self, attrs=None): 
     hours = [ (i, "%02d" %(i)) for i in range(0, 24) ] 
     minutes = [ (i, "%02d" %(i)) for i in range(0, 60) ] 
     _widgets = (
      widgets.Select(attrs=attrs, choices=hours), 
      widgets.Select(attrs=attrs, choices=minutes), 
      ) 
     super(MilitaryTimeWidget, self).__init__(_widgets, attrs) 

    def decompress(self, value): 
     print "******** %s" %value 
     if value: 
      return [int(value.hour), int(value.minute)] 
     return [None, None] 

    def value_from_datadict(self, data, files, name): 
     hour = data.get("%s_0" %name, None) 
     minute = data.get("%s_1" %name, None) 
     if hour and minute: 
      hour = int(hour) 
      minute = int(minute) 
      return datetime.time(hour=hour, minute=minute) 
     return None 

在我的形式,我打電話像小部件:

arrival_time = forms.TimeField(label="Arrival Time", required=False, widget=MilitaryTimeWidget()) 
+0

我不會把它作爲答案,因爲它與你的問題是正交的,但我想不出爲什麼你想要這個UI。這比在文本框中正確解析/驗證的文本輸入框更好/更快/更容易? – 2009-02-12 17:58:34

回答

0

我不能重現該問題:

>>> class MyForm(forms.Form): 
...  t = forms.TimeField(widget=MilitaryTimeWidget()) 
... 
>>> print MyForm(data={'t_0': '13', 't_1': '34'}) 
******** 13:34:00 
<tr><th><label for="id_t_0">T:</label></th><td><select name="t_0" id="id_t_0"> 
<option value="0">00</option> 
[...] 
<option value="13" selected="selected">13</option> 
[...] 
<option value="23">23</option> 
</select><select name="t_1" id="id_t_1"> 
<option value="0">00</option> 
[...] 
<option value="34" selected="selected">34</option> 
[...] 
<option value="59">59</option> 
</select></td></tr> 

檢查您的request.POST是正確的。

作爲一個旁註,你確定這個小部件提供了很好的可用性嗎?點擊4分鼠標和分鐘組合框的滾動可能...

+1

我認爲我的問題是我沒有試圖使用POST數據填充表單,而是試圖使用我的模型之一進行填充。 由於我遺漏了我傳入的數據中的arrival_time_0和arrival_time_1(給每個選擇小部件的名稱),因此它沒有被填充。 – ashchristopher 2009-02-12 14:23:14

+1

在傳遞給表單之前,我認爲這樣看起來相當笨拙和非pythonic,故意將這些數據分割開來。思考? – ashchristopher 2009-02-12 14:23:53

3

this line in the docstring for MultiWidget

你可能會想使用這個類MultiValueField。

這就是問題的根源。你也許能夠使用單部件工作方式(Marty說可能在Pro Django中,但我從來沒有嘗試過,我認爲它可能會更多工作),但在這種情況下,您的小部件不應該是MultiWidget的子類。

你需要做的(如果你想跟着MultiWidget/MultiValueField路徑)是什麼:

  • 刪除您value_from_datadict方法
  • 定義MultiValueField一個子類與壓縮的定義()方法你可以在value_from_datadict()中完成目前正在做的任務(將數字列表轉換爲datetime.time對象)
  • 將你的Widget設置爲你自定義表單域的缺省值(使用Widget類屬性)
  • 要麼創建一個自定義模型字段,它將從Formfield()方法返回自定義表單字段,或者手動將自定義表單字段用作ModelForm中的字段覆蓋。

然後一切都會正常工作。