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のdocstringの次の行に注意してください。

このクラスをMultiValueFieldで使用することをお勧めします。

それがあなたの問題の根源です。単一ウィジェットのみのアプローチを機能させることができるかもしれませんが(マーティはPro Djangoで可能だと言っていますが、私はそれを試したことがなく、もっとうまくいく可能性が高いと思います)、その場合、ウィジェットはすべきではありません。 MultiWidgetのサブクラスになります。

(MultiWidget / MultiValueFieldパスをたどる場合)必要なことは次のとおりです。

  • value_from_datadictメソッドを削除します
  • value_from_datadict()で現在実行しているタスクを実行するcompress()メソッドの定義を使用してMultiValueFieldのサブクラスを定義します(数値のリストを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 が正しいことを確認してください。

余談ですが、このウィジェットの使いやすさは確かですか? マウスを 4 回クリックするだけで、分のコンボボックスをスクロールできます...

于 2009-02-12T10:00:40.563 に答える