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

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

    === modified file 'django/newforms/extras/widgets.py'
     
    1616    This also serves as an example of a Widget that has more than one HTML
    1717    element and hence implements value_from_datadict.
    1818    """
     19    default_outer_class = 'select-date'
     20
    1921    month_field = '%s_month'
    2022    day_field = '%s_day'
    2123    year_field = '%s_year'
    2224
    23     def __init__(self, attrs=None, years=None):
     25    def __init__(self, attrs=None, outer_attrs=None, years=None):
    2426        # 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)
    2628        if years:
    2729            self.years = years
    2830        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 = 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()
    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'
     
    129129    __metaclass__ = MediaDefiningClass
    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
     132    default_outer_class = ''
    132133
    133     def __init__(self, attrs=None):
     134    def __init__(self, attrs=None, outer_attrs=None):
    134135        if attrs is not None:
    135136            self.attrs = attrs.copy()
    136137        else:
    137138            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
    138145
    139146    def __deepcopy__(self, memo):
    140147        obj = copy.copy(self)
    141148        obj.attrs = self.attrs.copy()
     149        obj.outer_attrs = self.outer_attrs.copy()
    142150        memo[id(self)] = obj
    143151        return obj
    144152
     
    193201
    194202class TextInput(Input):
    195203    input_type = 'text'
     204    default_outer_class = 'text'
    196205
    197206class PasswordInput(Input):
    198207    input_type = 'password'
     208    default_outer_class = 'password'
    199209
    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)
    202212        self.render_value = render_value
    203213
    204214    def render(self, name, value, attrs=None):
     
    208218class HiddenInput(Input):
    209219    input_type = 'hidden'
    210220    is_hidden = True
     221    default_outer_class = 'hidden'
     222
    211223
    212224class MultipleHiddenInput(HiddenInput):
    213225    """
    214226    A widget that handles <input type="hidden"> for fields that have a list
    215227    of values.
    216228    """
    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)
    219232        # choices can be any iterable
    220233        self.choices = choices
    221234
     
    232245class FileInput(Input):
    233246    input_type = 'file'
    234247    needs_multipart_form = True
     248    default_outer_class = 'file'
    235249
    236250    def render(self, name, value, attrs=None):
    237251        return super(FileInput, self).render(name, None, attrs=attrs)
     
    241255        return files.get(name, None)
    242256
    243257class Textarea(Widget):
    244     def __init__(self, attrs=None):
     258    default_outer_class = 'textarea'
     259    def __init__(self, attrs=None, outer_attrs=None):
    245260        # The 'rows' and 'cols' attributes are required for HTML correctness.
    246         self.attrs = {'cols': '40', 'rows': '10'}
     261        default_attrs = {'cols': '40', 'rows': '10'}
    247262        if attrs:
    248             self.attrs.update(attrs)
     263            default_attrs.update(attrs)
     264        super(Textarea, self, default_attrs, outer_attrs)
    249265
    250266    def render(self, name, value, attrs=None):
    251267        if value is None: value = ''
     
    255271
    256272class DateTimeInput(Input):
    257273    input_type = 'text'
     274    default_outer_class = 'date-time'
    258275    format = '%Y-%m-%d %H:%M:%S'     # '2006-10-25 14:30:59'
    259276
    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)
    262279        if format:
    263280            self.format = format
    264281
     
    270287        return super(DateTimeInput, self).render(name, value, attrs)
    271288
    272289class 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)
    275293        # check_test is a callable that takes a value and returns True
    276294        # if the checkbox should be checked for that value.
    277295        self.check_test = check_test
     
    296314        return super(CheckboxInput, self).value_from_datadict(data, files, name)
    297315
    298316class 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)
    301320        # choices can be any iterable, but we may need to render this widget
    302321        # multiple times. Thus, collapse it into a list so it can be consumed
    303322        # more than once.
     
    316335        return u'\n'.join(output)
    317336
    318337class NullBooleanSelect(Select):
     338    default_outer_class = 'null-boolean-select'
    319339    """
    320340    A Select Widget intended to be used with NullBooleanField.
    321341    """
    322     def __init__(self, attrs=None):
     342    def __init__(self, attrs=None, outer_attrs=None):
    323343        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)
    325345
    326346    def render(self, name, value, attrs=None, choices=()):
    327347        try:
     
    352372        output.append(u'</select>')
    353373        return u'\n'.join(output)
    354374
     375    default_outer_class = 'select-multiply'
     376
    355377    def value_from_datadict(self, data, files, name):
    356378        if isinstance(data, MultiValueDict):
    357379            return data.getlist(name)
     
    362384    An object used by RadioFieldRenderer that represents a single
    363385    <input type='radio'>.
    364386    """
    365 
     387    default_outer_class = 'radio'
    366388    def __init__(self, name, value, attrs, choice, index):
    367389        self.name, self.value = name, value
    368390        self.attrs = attrs
     
    409431        return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self])
    410432
    411433class RadioSelect(Select):
    412 
     434    default_outer_class = 'radio-select'
    413435    def __init__(self, *args, **kwargs):
    414436        self.renderer = kwargs.pop('renderer', None)
    415437        if not self.renderer:
     
    438460    id_for_label = classmethod(id_for_label)
    439461
    440462class CheckboxSelectMultiple(SelectMultiple):
     463    default_outer_class = 'checkbox-select-multiply'
    441464    def render(self, name, value, attrs=None, choices=()):
    442465        if value is None: value = []
    443466        has_id = attrs and 'id' in attrs
     
    490513
    491514    You'll probably want to use this class with MultiValueField.
    492515    """
    493     def __init__(self, widgets, attrs=None):
     516    def __init__(self, widgets, attrs=None, outer_attrs=None):
    494517        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)
    496519
    497520    def render(self, name, value, attrs=None):
    498521        # value is a list of values, each corresponding to a widget
     
    552575    """
    553576    A Widget that splits datetime input into two <input type="text"> boxes.
    554577    """
    555     def __init__(self, attrs=None):
     578    default_outer_class = 'split-date-time'
     579    def __init__(self, attrs=None, outer_attrs=None):
    556580        widgets = (TextInput(attrs=attrs), TextInput(attrs=attrs))
    557         super(SplitDateTimeWidget, self).__init__(widgets, attrs)
     581        super(SplitDateTimeWidget, self).__init__(widgets, attrs, outer_attrs)
    558582
    559583    def decompress(self, value):
    560584        if value:
Back to Top