=== modified file 'django/newforms/extras/widgets.py'
|
|
|
|
| 16 | 16 | This also serves as an example of a Widget that has more than one HTML |
| 17 | 17 | element and hence implements value_from_datadict. |
| 18 | 18 | """ |
| | 19 | default_outer_class = 'select-date' |
| | 20 | |
| 19 | 21 | month_field = '%s_month' |
| 20 | 22 | day_field = '%s_day' |
| 21 | 23 | year_field = '%s_year' |
| 22 | 24 | |
| 23 | | def __init__(self, attrs=None, years=None): |
| | 25 | def __init__(self, attrs=None, outer_attrs=None, years=None): |
| 24 | 26 | # years is an optional list/tuple of years to use in the "year" select box. |
| 25 | | self.attrs = attrs or {} |
| | 27 | super(SelectDateWidget, self).__init__(attrs, outer_attrs) |
| 26 | 28 | if years: |
| 27 | 29 | self.years = years |
| 28 | 30 | else: |
=== modified file 'django/newforms/forms.py'
|
|
|
|
| 131 | 131 | top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors]) |
| 132 | 132 | hidden_fields.append(unicode(bf)) |
| 133 | 133 | else: |
| | 134 | outer_attrs = bf.field.widget.outer_attrs |
| | 135 | outer_class = outer_attrs.pop('class', '') |
| | 136 | if bf.field.required: |
| | 137 | outer_class += ' required' |
| | 138 | if bf_errors: |
| | 139 | outer_class += ' error' |
| | 140 | if outer_class: |
| | 141 | outer_attrs['class'] = outer_class.strip() |
| 134 | 142 | if errors_on_separate_row and bf_errors: |
| 135 | 143 | output.append(error_row % force_unicode(bf_errors)) |
| 136 | 144 | if bf.label: |
| … |
… |
|
| 146 | 154 | help_text = help_text_html % force_unicode(field.help_text) |
| 147 | 155 | else: |
| 148 | 156 | help_text = u'' |
| 149 | | output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label), 'field': unicode(bf), 'help_text': help_text}) |
| | 157 | output.append(normal_row % {'errors': force_unicode(bf_errors), 'label': force_unicode(label), |
| | 158 | 'field': unicode(bf), 'help_text': help_text, 'outer_attrs': flatatt(outer_attrs)}) |
| 150 | 159 | if top_errors: |
| 151 | 160 | output.insert(0, error_row % top_errors) |
| 152 | 161 | if hidden_fields: # Insert any hidden fields in the last row. |
| … |
… |
|
| 161 | 170 | |
| 162 | 171 | def as_table(self): |
| 163 | 172 | "Returns this form rendered as HTML <tr>s -- excluding the <table></table>." |
| 164 | | return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False) |
| | 173 | return self._html_output(u'<tr%(outer_attrs)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False) |
| 165 | 174 | |
| 166 | 175 | def as_ul(self): |
| 167 | 176 | "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>." |
| 168 | | return self._html_output(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False) |
| | 177 | return self._html_output(u'<li%(outer_attrs)s(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False) |
| 169 | 178 | |
| 170 | 179 | def as_p(self): |
| 171 | 180 | "Returns this form rendered as HTML <p>s." |
| 172 | | return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'%s', '</p>', u' %s', True) |
| | 181 | return self._html_output(u'<p%(outer_attrs)s>%(label)s %(field)s%(help_text)s</p>', u'%s', '</p>', u' %s', True) |
| 173 | 182 | |
| 174 | 183 | def non_field_errors(self): |
| 175 | 184 | """ |
=== modified file 'django/newforms/widgets.py'
|
|
|
|
| 129 | 129 | __metaclass__ = MediaDefiningClass |
| 130 | 130 | is_hidden = False # Determines whether this corresponds to an <input type="hidden">. |
| 131 | 131 | needs_multipart_form = False # Determines does this widget need multipart-encrypted form |
| | 132 | default_outer_class = '' |
| 132 | 133 | |
| 133 | | def __init__(self, attrs=None): |
| | 134 | def __init__(self, attrs=None, outer_attrs=None): |
| 134 | 135 | if attrs is not None: |
| 135 | 136 | self.attrs = attrs.copy() |
| 136 | 137 | else: |
| 137 | 138 | self.attrs = {} |
| | 139 | if outer_attrs is not None: |
| | 140 | self.outer_attrs = outer_attrs.copy() |
| | 141 | else: |
| | 142 | self.outer_attrs = {} |
| | 143 | if 'class' not in self.outer_attrs: |
| | 144 | self.outer_attrs['class'] = self.default_outer_class |
| 138 | 145 | |
| 139 | 146 | def __deepcopy__(self, memo): |
| 140 | 147 | obj = copy.copy(self) |
| 141 | 148 | obj.attrs = self.attrs.copy() |
| | 149 | obj.outer_attrs = self.outer_attrs.copy() |
| 142 | 150 | memo[id(self)] = obj |
| 143 | 151 | return obj |
| 144 | 152 | |
| … |
… |
|
| 193 | 201 | |
| 194 | 202 | class TextInput(Input): |
| 195 | 203 | input_type = 'text' |
| | 204 | default_outer_class = 'text' |
| 196 | 205 | |
| 197 | 206 | class PasswordInput(Input): |
| 198 | 207 | input_type = 'password' |
| | 208 | default_outer_class = 'password' |
| 199 | 209 | |
| 200 | | def __init__(self, attrs=None, render_value=True): |
| 201 | | super(PasswordInput, self).__init__(attrs) |
| | 210 | def __init__(self, attrs=None, outer_attrs=None, render_value=True): |
| | 211 | super(PasswordInput, self).__init__(attrs, outer_attrs) |
| 202 | 212 | self.render_value = render_value |
| 203 | 213 | |
| 204 | 214 | def render(self, name, value, attrs=None): |
| … |
… |
|
| 208 | 218 | class HiddenInput(Input): |
| 209 | 219 | input_type = 'hidden' |
| 210 | 220 | is_hidden = True |
| | 221 | default_outer_class = 'hidden' |
| | 222 | |
| 211 | 223 | |
| 212 | 224 | class MultipleHiddenInput(HiddenInput): |
| 213 | 225 | """ |
| 214 | 226 | A widget that handles <input type="hidden"> for fields that have a list |
| 215 | 227 | of values. |
| 216 | 228 | """ |
| 217 | | def __init__(self, attrs=None, choices=()): |
| 218 | | super(MultipleHiddenInput, self).__init__(attrs) |
| | 229 | default_outer_class = 'multiply-hidden' |
| | 230 | def __init__(self, attrs=None, outer_attrs=None, choices=()): |
| | 231 | super(MultipleHiddenInput, self).__init__(attrs, outer_attrs) |
| 219 | 232 | # choices can be any iterable |
| 220 | 233 | self.choices = choices |
| 221 | 234 | |
| … |
… |
|
| 232 | 245 | class FileInput(Input): |
| 233 | 246 | input_type = 'file' |
| 234 | 247 | needs_multipart_form = True |
| | 248 | default_outer_class = 'file' |
| 235 | 249 | |
| 236 | 250 | def render(self, name, value, attrs=None): |
| 237 | 251 | return super(FileInput, self).render(name, None, attrs=attrs) |
| … |
… |
|
| 241 | 255 | return files.get(name, None) |
| 242 | 256 | |
| 243 | 257 | class Textarea(Widget): |
| 244 | | def __init__(self, attrs=None): |
| | 258 | default_outer_class = 'textarea' |
| | 259 | def __init__(self, attrs=None, outer_attrs=None): |
| 245 | 260 | # The 'rows' and 'cols' attributes are required for HTML correctness. |
| 246 | | self.attrs = {'cols': '40', 'rows': '10'} |
| | 261 | default_attrs = {'cols': '40', 'rows': '10'} |
| 247 | 262 | if attrs: |
| 248 | | self.attrs.update(attrs) |
| | 263 | default_attrs.update(attrs) |
| | 264 | super(Textarea, self, default_attrs, outer_attrs) |
| 249 | 265 | |
| 250 | 266 | def render(self, name, value, attrs=None): |
| 251 | 267 | if value is None: value = '' |
| … |
… |
|
| 255 | 271 | |
| 256 | 272 | class DateTimeInput(Input): |
| 257 | 273 | input_type = 'text' |
| | 274 | default_outer_class = 'date-time' |
| 258 | 275 | format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59' |
| 259 | 276 | |
| 260 | | def __init__(self, attrs=None, format=None): |
| 261 | | super(DateTimeInput, self).__init__(attrs) |
| | 277 | def __init__(self, attrs=None, outer_attrs=None, format=None): |
| | 278 | super(DateTimeInput, self).__init__(attrs, outer_attrs) |
| 262 | 279 | if format: |
| 263 | 280 | self.format = format |
| 264 | 281 | |
| … |
… |
|
| 270 | 287 | return super(DateTimeInput, self).render(name, value, attrs) |
| 271 | 288 | |
| 272 | 289 | class CheckboxInput(Widget): |
| 273 | | def __init__(self, attrs=None, check_test=bool): |
| 274 | | super(CheckboxInput, self).__init__(attrs) |
| | 290 | default_outer_class = 'checkbox' |
| | 291 | def __init__(self, attrs=None, outer_attrs=None, check_test=bool): |
| | 292 | super(CheckboxInput, self).__init__(attrs, outer_attrs) |
| 275 | 293 | # check_test is a callable that takes a value and returns True |
| 276 | 294 | # if the checkbox should be checked for that value. |
| 277 | 295 | self.check_test = check_test |
| … |
… |
|
| 296 | 314 | return super(CheckboxInput, self).value_from_datadict(data, files, name) |
| 297 | 315 | |
| 298 | 316 | class Select(Widget): |
| 299 | | def __init__(self, attrs=None, choices=()): |
| 300 | | super(Select, self).__init__(attrs) |
| | 317 | default_outer_class = 'select' |
| | 318 | def __init__(self, attrs=None, outer_attrs=None, choices=()): |
| | 319 | super(Select, self).__init__(attrs, outer_attrs) |
| 301 | 320 | # choices can be any iterable, but we may need to render this widget |
| 302 | 321 | # multiple times. Thus, collapse it into a list so it can be consumed |
| 303 | 322 | # more than once. |
| … |
… |
|
| 316 | 335 | return u'\n'.join(output) |
| 317 | 336 | |
| 318 | 337 | class NullBooleanSelect(Select): |
| | 338 | default_outer_class = 'null-boolean-select' |
| 319 | 339 | """ |
| 320 | 340 | A Select Widget intended to be used with NullBooleanField. |
| 321 | 341 | """ |
| 322 | | def __init__(self, attrs=None): |
| | 342 | def __init__(self, attrs=None, outer_attrs=None): |
| 323 | 343 | choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')), (u'3', ugettext('No'))) |
| 324 | | super(NullBooleanSelect, self).__init__(attrs, choices) |
| | 344 | super(NullBooleanSelect, self).__init__(attrs, outer_attrs, choices) |
| 325 | 345 | |
| 326 | 346 | def render(self, name, value, attrs=None, choices=()): |
| 327 | 347 | try: |
| … |
… |
|
| 352 | 372 | output.append(u'</select>') |
| 353 | 373 | return u'\n'.join(output) |
| 354 | 374 | |
| | 375 | default_outer_class = 'select-multiply' |
| | 376 | |
| 355 | 377 | def value_from_datadict(self, data, files, name): |
| 356 | 378 | if isinstance(data, MultiValueDict): |
| 357 | 379 | return data.getlist(name) |
| … |
… |
|
| 362 | 384 | An object used by RadioFieldRenderer that represents a single |
| 363 | 385 | <input type='radio'>. |
| 364 | 386 | """ |
| 365 | | |
| | 387 | default_outer_class = 'radio' |
| 366 | 388 | def __init__(self, name, value, attrs, choice, index): |
| 367 | 389 | self.name, self.value = name, value |
| 368 | 390 | self.attrs = attrs |
| … |
… |
|
| 409 | 431 | return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self]) |
| 410 | 432 | |
| 411 | 433 | class RadioSelect(Select): |
| 412 | | |
| | 434 | default_outer_class = 'radio-select' |
| 413 | 435 | def __init__(self, *args, **kwargs): |
| 414 | 436 | self.renderer = kwargs.pop('renderer', None) |
| 415 | 437 | if not self.renderer: |
| … |
… |
|
| 438 | 460 | id_for_label = classmethod(id_for_label) |
| 439 | 461 | |
| 440 | 462 | class CheckboxSelectMultiple(SelectMultiple): |
| | 463 | default_outer_class = 'checkbox-select-multiply' |
| 441 | 464 | def render(self, name, value, attrs=None, choices=()): |
| 442 | 465 | if value is None: value = [] |
| 443 | 466 | has_id = attrs and 'id' in attrs |
| … |
… |
|
| 490 | 513 | |
| 491 | 514 | You'll probably want to use this class with MultiValueField. |
| 492 | 515 | """ |
| 493 | | def __init__(self, widgets, attrs=None): |
| | 516 | def __init__(self, widgets, attrs=None, outer_attrs=None): |
| 494 | 517 | self.widgets = [isinstance(w, type) and w() or w for w in widgets] |
| 495 | | super(MultiWidget, self).__init__(attrs) |
| | 518 | super(MultiWidget, self).__init__(attrs, outer_attrs) |
| 496 | 519 | |
| 497 | 520 | def render(self, name, value, attrs=None): |
| 498 | 521 | # value is a list of values, each corresponding to a widget |
| … |
… |
|
| 552 | 575 | """ |
| 553 | 576 | A Widget that splits datetime input into two <input type="text"> boxes. |
| 554 | 577 | """ |
| 555 | | def __init__(self, attrs=None): |
| | 578 | default_outer_class = 'split-date-time' |
| | 579 | def __init__(self, attrs=None, outer_attrs=None): |
| 556 | 580 | widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs)) |
| 557 | | super(SplitDateTimeWidget, self).__init__(widgets, attrs) |
| | 581 | super(SplitDateTimeWidget, self).__init__(widgets, attrs, outer_attrs) |
| 558 | 582 | |
| 559 | 583 | def decompress(self, value): |
| 560 | 584 | if value: |