Пользовательский виджет django - не заполнено () arg не заполнено - PullRequest
3 голосов
/ 12 февраля 2009

В качестве упражнения я пытаюсь создать собственный виджет django для 24-часовых часов. Виджет будет MultiWidget - поле выбора для каждого поля.

Я пытаюсь следить за документами онлайн (довольно редко) и смотрю на книгу про Джанго, но, похоже, не могу понять это. Я на правильном пути? Я могу сохранить свои данные из формы, но когда я предварительно заполняю форму, форма не имеет предыдущих значений.

Кажется, проблема в том, что аргумент 'value' метода depress () всегда пуст, поэтому мне нечего интерпретировать.

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

Ответы [ 2 ]

4 голосов
/ 12 февраля 2009

Примечание эта строка в строке документации для MultiWidget :

Возможно, вы захотите использовать этот класс с MultiValueField.

Это корень вашей проблемы. Возможно, вам удастся заставить работать подход, основанный только на одном виджете (Марти говорит, что это возможно в Pro Django , но я никогда не пробовал это, и я думаю, что это, вероятно, будет больше работы), но в в этом случае ваш виджет не должен быть подклассом MultiWidget.

Что вам нужно сделать (если вы хотите следовать по пути MultiWidget / MultiValueField):

  • удалить ваш метод value_from_datadict
  • определяет подкласс MultiValueField с определением метода compress (), который выполняет задачу, которую вы сейчас выполняете, в value_from_datadict () (преобразование списка чисел в объект datetime.time)
  • установить виджет по умолчанию для поля пользовательской формы (используя атрибут класса виджета)
  • либо создайте пользовательское поле модели, которое возвращает ваше пользовательское поле формы из его метода formfield (), либо используйте ваше пользовательское поле формы вручную в качестве переопределения поля в ModelForm.

Тогда все будет просто работать.

0 голосов
/ 12 февраля 2009

Я не могу воспроизвести проблему:

>>> 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>

Убедитесь, что ваш запрос. ПОЧТА верна.

В качестве sidenote, вы уверены, что этот виджет дает хорошее удобство использования? Четыре щелчка мышью и возможная прокрутка комбинированного списка минут ...

...