3

作为一个练习,我正在尝试为 24 小时制创建一个自定义 django 小部件。小部件将是一个 MultiWidget - 每个字段的选择框。

我正在尝试在线关注文档(有点稀疏)并查看 Pro Django 书籍,但我似乎无法弄清楚。我在正确的轨道上吗?我可以保存表单中的数据,但是当我预填充表单时,表单没有以前的值。

似乎问题在于 decompress() 方法的“值”参数始终为空,所以我没有什么要解释的。

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())
4

2 回答 2

4

请注意MultiWidget 文档字符串中的这一行

您可能希望将此类与 MultiValueField 一起使用。

这就是你问题的根源。您也许可以使仅使用单个小部件的方法起作用(Marty 说在Pro Django中可以,但我从未尝试过,而且我认为它可能需要更多工作),但在这种情况下,您的小部件不应该t 是 MultiWidget 的子类。

您需要做的(如果您想遵循 MultiWidget/MultiValueField 路径)是:

  • 删除你的 value_from_datadict 方法
  • 使用 compress() 方法的定义定义MultiValueField的子类,该方法执行您当前在 value_from_datadict() 中执行的任务(将数字列表转换为 datetime.time 对象)
  • 将您的小部件设置为自定义表单字段的默认值(使用小部件类属性)
  • 要么创建一个自定义模型字段,该字段从其 formfield() 方法返回您的自定义表单字段,要么手动使用您的自定义表单字段作为 ModelForm 中的字段覆盖。

然后一切都会正常工作。

于 2009-02-12T18:26:20.473 回答
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 是否正确。

作为旁注,您确定此小部件具有良好的可用性吗?四次鼠标点击和分钟组合框的可能滚动......

于 2009-02-12T10:00:40.563 回答