Ticket #3515: 00-widget-outer-attrs.3.diff

File 00-widget-outer-attrs.3.diff, 8.7 KB (added by Petr Marhoun <petr.marhoun@…>, 7 years ago)
  • django/newforms/extras/widgets.py

    === modified file 'django/newforms/extras/widgets.py'
     
    2020    day_field = '%s_day'
    2121    year_field = '%s_year'
    2222
    23     def __init__(self, attrs=None, years=None):
     23    def __init__(self, attrs=None, outer_attrs=None, years=None):
    2424        # years is an optional list/tuple of years to use in the "year" select box.
    25         self.attrs = attrs or {}
     25        super(SelectDateWidget, self).__init__(attrs, outer_attrs)
    2626        if years:
    2727            self.years = years
    2828        else:
  • django/newforms/forms.py

    === modified file 'django/newforms/forms.py'
     
    131131                    top_errors.extend(['(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
    132132                hidden_fields.append(unicode(bf))
    133133            else:
     134                outer_attrs = bf.field.widget.outer_attrs
     135                outer_class_list = outer_attrs.pop('class', '').split()
     136                if bf.field.required:
     137                    outer_class_list.append('required')
     138                if bf_errors:
     139                    outer_class_list.append('error')
     140                if outer_class_list:
     141                    outer_attrs['class'] = ' '.join(outer_class_list)
    134142                if errors_on_separate_row and bf_errors:
    135143                    output.append(error_row % force_unicode(bf_errors))
    136144                if bf.label:
     
    146154                    help_text = help_text_html % force_unicode(field.help_text)
    147155                else:
    148156                    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)})
    150159        if top_errors:
    151160            output.insert(0, error_row % top_errors)
    152161        if hidden_fields: # Insert any hidden fields in the last row.
     
    161170
    162171    def as_table(self):
    163172        "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)
    165174
    166175    def as_ul(self):
    167176        "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)
    169178
    170179    def as_p(self):
    171180        "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)
    173182
    174183    def non_field_errors(self):
    175184        """
  • django/newforms/widgets.py

    === modified file 'django/newforms/widgets.py'
     
    130130    is_hidden = False          # Determines whether this corresponds to an <input type="hidden">.
    131131    needs_multipart_form = False # Determines does this widget need multipart-encrypted form
    132132
    133     def __init__(self, attrs=None):
     133    def __init__(self, attrs=None, outer_attrs=None):
    134134        if attrs is not None:
    135135            self.attrs = attrs.copy()
    136136        else:
    137137            self.attrs = {}
     138        if outer_attrs is not None:
     139            self.outer_attrs = outer_attrs.copy()
     140        else:
     141            self.outer_attrs = {}
    138142
    139143    def __deepcopy__(self, memo):
    140144        obj = copy.copy(self)
    141145        obj.attrs = self.attrs.copy()
     146        obj.outer_attrs = self.outer_attrs.copy()
    142147        memo[id(self)] = obj
    143148        return obj
    144149
     
    197202class PasswordInput(Input):
    198203    input_type = 'password'
    199204
    200     def __init__(self, attrs=None, render_value=True):
    201         super(PasswordInput, self).__init__(attrs)
     205    def __init__(self, attrs=None, outer_attrs=None, render_value=True):
     206        super(PasswordInput, self).__init__(attrs, outer_attrs)
    202207        self.render_value = render_value
    203208
    204209    def render(self, name, value, attrs=None):
     
    214219    A widget that handles <input type="hidden"> for fields that have a list
    215220    of values.
    216221    """
    217     def __init__(self, attrs=None, choices=()):
    218         super(MultipleHiddenInput, self).__init__(attrs)
     222    def __init__(self, attrs=None, outer_attrs=None, choices=()):
     223        super(MultipleHiddenInput, self).__init__(attrs, outer_attrs)
    219224        # choices can be any iterable
    220225        self.choices = choices
    221226
     
    241246        return files.get(name, None)
    242247
    243248class Textarea(Widget):
    244     def __init__(self, attrs=None):
     249    def __init__(self, attrs=None, outer_attrs=None):
    245250        # The 'rows' and 'cols' attributes are required for HTML correctness.
    246         self.attrs = {'cols': '40', 'rows': '10'}
     251        default_attrs = {'cols': '40', 'rows': '10'}
    247252        if attrs:
    248             self.attrs.update(attrs)
     253            default_attrs.update(attrs)
     254        super(Textarea, self, default_attrs, outer_attrs)
    249255
    250256    def render(self, name, value, attrs=None):
    251257        if value is None: value = ''
     
    257263    input_type = 'text'
    258264    format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
    259265
    260     def __init__(self, attrs=None, format=None):
    261         super(DateTimeInput, self).__init__(attrs)
     266    def __init__(self, attrs=None, outer_attrs=None, format=None):
     267        super(DateTimeInput, self).__init__(attrs, outer_attrs)
    262268        if format:
    263269            self.format = format
    264270
     
    270276        return super(DateTimeInput, self).render(name, value, attrs)
    271277
    272278class CheckboxInput(Widget):
    273     def __init__(self, attrs=None, check_test=bool):
    274         super(CheckboxInput, self).__init__(attrs)
     279    def __init__(self, attrs=None, outer_attrs=None, check_test=bool):
     280        super(CheckboxInput, self).__init__(attrs, outer_attrs)
    275281        # check_test is a callable that takes a value and returns True
    276282        # if the checkbox should be checked for that value.
    277283        self.check_test = check_test
     
    296302        return super(CheckboxInput, self).value_from_datadict(data, files, name)
    297303
    298304class Select(Widget):
    299     def __init__(self, attrs=None, choices=()):
    300         super(Select, self).__init__(attrs)
     305    def __init__(self, attrs=None, outer_attrs=None, choices=()):
     306        super(Select, self).__init__(attrs, outer_attrs)
    301307        # choices can be any iterable, but we may need to render this widget
    302308        # multiple times. Thus, collapse it into a list so it can be consumed
    303309        # more than once.
     
    319325    """
    320326    A Select Widget intended to be used with NullBooleanField.
    321327    """
    322     def __init__(self, attrs=None):
     328    def __init__(self, attrs=None, outer_attrs=None):
    323329        choices = ((u'1', ugettext('Unknown')), (u'2', ugettext('Yes')), (u'3', ugettext('No')))
    324         super(NullBooleanSelect, self).__init__(attrs, choices)
     330        super(NullBooleanSelect, self).__init__(attrs, outer_attrs, choices)
    325331
    326332    def render(self, name, value, attrs=None, choices=()):
    327333        try:
     
    490496
    491497    You'll probably want to use this class with MultiValueField.
    492498    """
    493     def __init__(self, widgets, attrs=None):
     499    def __init__(self, widgets, attrs=None, outer_attrs=None):
    494500        self.widgets = [isinstance(w, type) and w() or w for w in widgets]
    495         super(MultiWidget, self).__init__(attrs)
     501        super(MultiWidget, self).__init__(attrs, outer_attrs)
    496502
    497503    def render(self, name, value, attrs=None):
    498504        # value is a list of values, each corresponding to a widget
     
    552558    """
    553559    A Widget that splits datetime input into two <input type="text"> boxes.
    554560    """
    555     def __init__(self, attrs=None):
     561    def __init__(self, attrs=None, outer_attrs=None):
    556562        widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
    557         super(SplitDateTimeWidget, self).__init__(widgets, attrs)
     563        super(SplitDateTimeWidget, self).__init__(widgets, attrs, outer_attrs)
    558564
    559565    def decompress(self, value):
    560566        if value:
Back to Top