153 | | Wrapper around multiple other widgets |
| 153 | Wrapper around multiple other widgets. |
| 154 | |
| 155 | Here is an example of using the ``MultiWidget`` with the |
| 156 | ``us.forms.USPhoneNumberField`` in the ``localflavor`` package. |
| 157 | |
| 158 | .. code-block:: python |
| 159 | |
| 160 | class USSplitPhoneWidget(forms.MultiWidget): |
| 161 | """ |
| 162 | A widget that splits phone number input into three fields. |
| 163 | """ |
| 164 | def __init__(self, widgets=None, attrs=None): |
| 165 | if not widgets: |
| 166 | widgets = ( |
| 167 | forms.TextInput(attrs={'size':'3','maxlength':'3'}), |
| 168 | forms.TextInput(attrs={'size':'3','maxlength':'3'}), |
| 169 | forms.TextInput(attrs={'size':'4','maxlength':'4'}), |
| 170 | ) |
| 171 | super(USSplitPhoneWidget, self).__init__(widgets, attrs) |
| 172 | |
| 173 | def decompress(self, value): |
| 174 | """ |
| 175 | Accepts a single value which is extracted to populate the |
| 176 | provided widgets. |
| 177 | """ |
| 178 | if value: |
| 179 | return value.split('-') |
| 180 | return ("","","") |
| 181 | |
| 182 | def value_from_datadict(self, data, files, name): |
| 183 | """ |
| 184 | Modify the widget to return a single value for the |
| 185 | USPhoneNumberField. |
| 186 | """ |
| 187 | values = super(USSplitPhoneWidget, self).value_from_datadict(data, files, name) |
| 188 | if any(values): |
| 189 | values = (x.replace("-", "") for x in values) |
| 190 | return u'%s-%s-%s' % tuple(values) |
| 191 | return "" |
| 192 | |
| 193 | def format_output(self, rendered_widgets): |
| 194 | return '<span class="lparen">(</span>%s<span class="rparen">)</span>%s<span class="phone-dash">-</span>%s' % tuple(rendered_widgets) |
| 195 | |
| 196 | This widget would be used in a form as follows: |
| 197 | |
| 198 | .. code-block:: python |
| 199 | |
| 200 | from django.contrib.localflavor.us.forms import USPhoneNumberField |
| 201 | |
| 202 | class MyForm(forms.Form): |
| 203 | phone = USPhoneNumberField(label="Phone", |
| 204 | widget=USSplitPhoneWidget()) |
| 205 | |
| 206 | Testing MultiWidgets |
| 207 | ==================== |
| 208 | |
| 209 | A field using a MultiWidget splits form data into multiple form elements. |
| 210 | In the form above, which defined a field called ``phone`` split into three |
| 211 | widgets, the three rendered fields are named ``phone_0``, ``phone_1``, |
| 212 | and ``phone_2``. |
| 213 | |
| 214 | The following gives an example of testing this form field. |
| 215 | |
| 216 | .. code-block:: python |
| 217 | |
| 218 | class USSplitPhoneWidgetTest(TestCase): |
| 219 | |
| 220 | def test_field_validation(self): |
| 221 | |
| 222 | class TestPhoneForm(forms.Form): |
| 223 | phone = USPhoneNumberField(label="Phone", |
| 224 | widget=gfaforms.fields.USSplitPhoneWidget()) |
| 225 | |
| 226 | form = TestPhoneForm(data={ |
| 227 | "phone_0": "800", |
| 228 | "phone_1": "999", |
| 229 | "phone_2": "2000", |
| 230 | }) |
| 231 | self.assertTrue(form.is_valid()) |