I am resending this -- seems it didn't reach the last time, sorry if it
turns up twice
------------
I've been messing around with the new MultiValueField and MultiWidget.
I don't know if the shortcoming is with me or with the implementation
of the field and widget. Let's say I want to create a field that
displays two select fields that are related, I'll use currency display
as an example. The resulting HTML should look like:
<select name="budget_0" id="id_budget">
<option value="USD">USD</option>
<option value="EU">EU</option>
</select>
<select name="budget_1" id="id_budget">
<option value="1000">1000</option>
<option value="2000">2000</option>
</select>
and returns a value like "USD 1000". The implementation I have so far
is:
# Field
class MoneyField(MultiValueField):
def __init__(self, currency=(), amount=(), required=True,
widget=None, label=None, initial=None):
fields = (ChoiceField(choices=currency),
ChoiceField(choices=amount))
super(MoneyField, self).__init__(fields, required, widget,
label, initial)
def compress(self, data_list):
if data_list:
return " ".join(i for i in data_list)
return None
# Widget
class MoneyWidget(MultiWidget):
def __init__(self, attrs=None, currency=(), amount=()):
widgets = (Select(attrs=attrs, choices=currency),
Select(attrs=attrs, choices=amount))
super(MoneyWidget, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return value.split(' ', 1)
return ['', '']
The problem is, when I use the field I have to repeat the choices for
both widget and the field, like so:
CURRENCY_CHOICES = [('USD', 'USD'), ('EU', 'EU')]
AMOUNT_CHOICES = [('1000', '1000'), ('2000', '2000')]
class MyForm(forms.Form):
budget = MoneyField(
label="Vacation budget (hotel amount only)",
currency=CURRENCY_CHOICES,
amount=AMOUNT_CHOICES,
required=False,
widget=MoneyWidget(currency=CURRENCY_CHOICES,
amount=AMOUNT_CHOICES)
)
Am I doing something wrong here are is it just a caveat with using
ChoiceField? Any guidance would be appreciated.
Cheers!
The widget can be declared as part of the field, e.g.
# Field
class MoneyField(MultiValueField):
def __init__(self, currency=(), amount=(), required=True,
widget=None, label=None, initial=None):
widget = widget or MoneyWidget(currency=currency,
amount=amount)
.....
Or something like that.
Can I do this with a built-in tag ?
Chris
Canen, do you have the time to work out a full example? After much
trying I'm still not able to repeat the example without having to use
the double tuple values.
Justin
Nevermind. I misunderstood what you meant by repeating choices. The
choices themselves are doubled if you want the value/content pair of
the <select> to have the same string, but the list of choices need
only be supplied to the widget and not the field if you define the
widget as part of the field as canen has already said.
Justin
On Feb 19, 10:18 pm, "Justin Findlay" <jfind...@gmail.com> wrote:
> On Jan 25, 1:16 pm, "canen" <nesta.campb...@gmail.com> wrote:
>
> > Answering my own question:
> Thanks for the example!
I created another, but it uses initial data, and an object
representing the info.
class Postal(object):
def __init__(self, line1='', line2='', line3='', code=''):
self.line1 = line1
self.line2 = line2
self.line3 = line3
self.code = code
class PostalWidget(django.newforms.widgets.MultiWidget):
def __init__(self, attrs=None):
widgets = (django.newforms.widgets.TextInput(),
django.newforms.widgets.TextInput(),
django.newforms.widgets.TextInput(),
django.newforms.widgets.TextInput())
super(PostalWidget, self).__init__(widgets, attrs=attrs)
def decompress(self, value):
if value:
return [value.line1, value.line2, value.line3, value.code]
return [None, None, None, None]
class PostalField(django.newforms.fields.MultiValueField):
widget = PostalWidget
def __init__(self, required=True, widget=None, label=None,
initial=None):
fields = (django.newforms.fields.CharField(),
django.newforms.fields.CharField(),
django.newforms.fields.CharField(),
django.newforms.fields.CharField())
super(PostalField, self).__init__(fields=fields,
widget=widget, label=label, initial=initial)
def compress(self, data_list):
if data_list:
return Postal(data_list[0], data_list[1], data_list[2],
data_list[3])
return None
class EnrolmentForm(django.newforms.Form):
name = django.newforms.fields.CharField(label='Name')
surname = django.newforms.fields.CharField(label='Surname')
postalField = PostalField()
data= {'name':'piet', 'surname':'plesier', 'postalField_0' : 'cs',
'postalField_1' : 'pretoria', 'postalField_2' :
'Hatfield' ,'postalField_3' : '0084'}
#initial= {'name':'piet', 'surname':'plesier', 'postalField' :
Postal(line1='pompies')}
initial= {'name':'piet', 'surname':'plesier'}
f = EnrolmentForm(initial=initial)
print f.as_p()
f = EnrolmentForm(data=data)
print f.is_valid()
print f.errors
print f.clean_data