Подкласс мультивиджета django не вызывает depress()
Я пытаюсь реализовать MultiValueField для записей IP-адресов / доменных имен. Это работает, как ожидается, для ввода данных. Моя проблема заключается в том, что если я хочу отобразить форму, привязанную к конкретным данным, поле IP-адрес / имя домена остается пустым. Все остальные поля заполнены требуемыми данными. Если я использую обычный CharField, я получаю данные, которые я ожидаю. Но это не работает с моим настраиваемым полем. Я проследил это до того факта, что мой пользовательский MultiWidget не вызывает его метод распаковки.
Вот мое поле:
class accessIPField(forms.MultiValueField):
"""
custom Field for access IP
"""
def __init__(self, *args, **kwargs):
self.fields=(
forms.IPAddressField(label='IP Adress'),
forms.CharField(max_length=50,label='Domain Name')
)
self.widget=accessIPWidget()
super(accessIPField,self).__init__(self.fields,self.widget, *args, **kwargs)
def compress(self,data_list):
if data_list:
return " ".join(data_list)
А вот и мой виджет:
class accessIPWidget(forms.MultiWidget):
"""
Widget to display IP Adress / Domain name pairs
"""
def __init__(self,*args,**kwargs):
self.widgets=(forms.TextInput(),forms.TextInput())
super(accessIPWidget,self).__init__(self.widgets,*args,**kwargs)
def decompress(self,value):
print 'decompress called'
if value:
return value.rsplit()
return [None,None]
def format_output(self, rendered_widgets):
return u'\n'.join(rendered_widgets)
Все это называется (в более широком контексте) как
self.fields['access_IPs'] = accessIPField()
Теперь, как вы можете видеть, я поместил оператор print в свой метод сжатия, и мне так и не удалось увидеть это утверждение. Кроме того, если я переименую сжатие в нечто вроде foobar, я ожидал бы (согласно коду django для MultiWidget) получить NotImplementedError, что не так. Какие-либо предложения?
Я использую Python 2.6.5, Django 1.1 на сервере Ubuntu 10.04.
1 ответ
Оказывается, проблема была в методе value_from_datadict(), реализованном MultiWidget. Прежде всего, он уже вернул список, поэтому не вызывался метод deppress(). Во-вторых, он всегда восстанавливал список [Нет, Нет], поэтому связанная форма оставалась пустой.
Мне нужно было реализовать свой собственный (в моем классе accessIPWidget):
def value_from_datadict(self, data, files, name):
try:
return data.get(name,None).rsplit()
except AttributeError:
return [widget.value_from_datadict(data, files, name + '_%s' % i) for i, widget in enumerate(self.widgets)]
Теперь последняя строка - это то, что сделал оригинальный метод. Чтобы получить данные в связанной форме, мне нужно было добавить data.get(name,None).rsplit().
Насколько я понимаю, оригинальный метод value_from_datadict работает только для несвязанных полей. Потому что это меняет имя исходного поля на name + '_%s', которое вы получаете, нажимая кнопку отправки. Чтобы заполнить связанный метод, запрос данных должен запрашиваться только для "имени".
Хм, не уверен, есть ли способ обойти это, но мне кажется, что это поведение должно быть где-то задокументировано. Может я что то не так понял?