Ticket #6631: 01-newforms-options.2.diff

File 01-newforms-options.2.diff, 9.1 KB (added by Petr Marhoun <petr.marhoun@…>, 7 years ago)
  • django/newforms/forms.py

    === modified file 'django/newforms/forms.py'
     
    77from django.utils.html import conditional_escape
    88from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
    99from django.utils.safestring import mark_safe
     10from django.utils.text import capfirst
    1011
    1112from fields import FileField
    1213from widgets import TextInput, Textarea
     
    2425
    2526class FormOptions(object):
    2627    def __init__(self, options=None):
     28        # main options
    2729        self.fieldsets = getattr(options, 'fieldsets', None)
    2830        self.fields = getattr(options, 'fields', None)
    2931        self.exclude = getattr(options, 'exclude', None)
     32        # other options
     33        self.error_class = getattr(options, 'error_class', ErrorList)
     34        self.error_row_class = getattr(options, 'error_row_class', 'error')
     35        self.hidden_row_class = getattr(options, 'hidden_row_class', 'hidden')
     36        self.label_capfirst = getattr(options, 'label_capfirst', True)
     37        self.label_suffix = getattr(options, 'label_suffix', ':')
     38        self.required_row_class = getattr(options, 'required_row_class', 'required')
     39        self.validation_order = getattr(options, 'validation_order', None)
    3040
    3141class FormMetaclass(type):
    3242    def __new__(cls, name, bases, attrs):
     
    4252    # class is different than Form. See the comments by the Form class for more
    4353    # information. Any improvements to the form API should be made to *this*
    4454    # class, not to the Form class.
    45     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
    46                  initial=None, error_class=ErrorList, label_suffix=':'):
     55    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None):
    4756        self.is_bound = data is not None or files is not None
    4857        self.data = data or {}
    4958        self.files = files or {}
    5059        self.auto_id = auto_id
    5160        self.prefix = prefix
    5261        self.initial = initial or {}
    53         self.error_class = error_class
    54         self.label_suffix = label_suffix
    5562        self._errors = None # Stores the errors after clean() has been called.
    5663
    5764        # The base_fields class attribute is the *class-wide* definition of
     
    120127    def _label_tag_html_output(self, bf, label_tag_html):
    121128        "Helper function for outputting HTML from a label. Used by _widget_html_output."
    122129        label, label_id = bf.label, bf.label_id
    123         if self.label_suffix and label and label[-1] not in ':?.!':
    124             label += self.label_suffix
     130        if self._meta.label_suffix and label and label[-1] not in ':?.!':
     131            label += self._meta.label_suffix
    125132        if label and label_id:
    126133            return label_tag_html % {
    127134                'label': label,
     
    178185
    179186    def _hidden_fields_html_output(self, hidden_fields, hidden_fields_html):
    180187        "Helper function for outputting HTML from a hidden fields. Used by _html_output."
     188        if self._meta.hidden_row_class:
     189            attrs = u' class="%s"' % self._meta.hidden_row_class
     190        else:
     191            attrs = u''
    181192        return hidden_fields_html % {
     193            'attrs': attrs,
    182194            'hidden_fields': u''.join(hidden_fields),
    183195        }
    184196
     
    222234            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<table>',
    223235            'fieldset_end_html': u'</table>\n</fieldset>',
    224236            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    225             'hidden_fields_html': u'<tr><td colspan="2">%(hidden_fields)s</td></tr>',
     237            'hidden_fields_html': u'<tr%(attrs)s><td colspan="2">%(hidden_fields)s</td></tr>',
    226238        }
    227239        return self._html_output(**kwargs)
    228240
     
    236248            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<ul>',
    237249            'fieldset_end_html': u'</ul>\n</fieldset>',
    238250            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    239             'hidden_fields_html': u'<li>%(hidden_fields)s</li>',
     251            'hidden_fields_html': u'<li%(attrs)s>%(hidden_fields)s</li>',
    240252        }
    241253        return self._html_output(**kwargs)
    242254
     
    250262            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s',
    251263            'fieldset_end_html': u'</fieldset>',
    252264            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    253             'hidden_fields_html': u'<p>%(hidden_fields)s</p>',
     265            'hidden_fields_html': u'<p%(attrs)>%(hidden_fields)s</p>',
    254266        }
    255267        return self._html_output(**kwargs)
    256268
     
    260272        field -- i.e., from Form.clean(). Returns an empty ErrorList if there
    261273        are none.
    262274        """
    263         return self.errors.get(NON_FIELD_ERRORS, self.error_class())
     275        return self.errors.get(NON_FIELD_ERRORS, self._meta.error_class())
    264276
    265277    def full_clean(self):
    266278        """
     
    271283        if not self.is_bound: # Stop further processing.
    272284            return
    273285        self.cleaned_data = {}
    274         for name, field in self.fields.items():
     286        if self._meta.validation_order:
     287            items = [(name, self.fields[name]) for name in self._meta.validation_order]
     288        else:
     289            items = self.fields.items()
     290        for name, field in items:
    275291            # value_from_datadict() gets the data from the data dictionaries.
    276292            # Each widget type knows how to retrieve its own data, because some
    277293            # widgets split data over several HTML fields.
     
    287303                    value = getattr(self, 'clean_%s' % name)()
    288304                    self.cleaned_data[name] = value
    289305            except ValidationError, e:
    290                 self._errors[name] = self.error_class(e.messages)
     306                self._errors[name] = self._meta.error_class(e.messages)
    291307                if name in self.cleaned_data:
    292308                    del self.cleaned_data[name]
    293309        try:
    294310            self.cleaned_data = self.clean()
    295311        except ValidationError, e:
    296             self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
     312            self._errors[NON_FIELD_ERRORS] = self._meta.error_class(e.messages)
    297313        if self._errors:
    298314            delattr(self, 'cleaned_data')
    299315
     
    344360        Returns an ErrorList for this field. Returns an empty ErrorList
    345361        if there are none.
    346362        """
    347         return self.form.errors.get(self.name, self.form.error_class())
     363        return self.form.errors.get(self.name, self.form._meta.error_class())
    348364    errors = property(_errors)
    349365
    350366    def as_widget(self, widget=None, attrs=None):
     
    395411        if self.field.label is None:
    396412            return pretty_name(self.name)
    397413        else:
    398             return conditional_escape(force_unicode(self.field.label))
     414            label = conditional_escape(force_unicode(self.field.label))
     415            if self.form._meta.label_capfirst:
     416                label = capfirst(label)
     417            return label
    399418    label = property(_label)
    400419
    401420    def _label_id(self):
     
    414433    help_text = property(_help_text)
    415434
    416435    def _row_attrs(self):
    417         "Returns row attributes for this field as safe HTML."
    418         return flatatt(self.widget.row_attrs)
     436        "Returns row attributes for this field as safe HTML code."
     437        attrs = self.widget.row_attrs.copy()
     438        class_list = attrs.pop('class', '').split()
     439        if self.form._meta.error_row_class and self.errors:
     440            class_list.append(self.form._meta.error_row_class)
     441        if self.form._meta.required_row_class and self.field.required:
     442            class_list.append(self.form._meta.required_row_class)
     443        if class_list:
     444            attrs['class'] = u' '.join(class_list)
     445        return flatatt(attrs)
    419446    row_attrs = property(_row_attrs)
    420447
    421448    def label_tag(self, contents=None, attrs=None):
  • django/newforms/models.py

    === modified file 'django/newforms/models.py'
     
    99from django.utils.encoding import smart_unicode
    1010from django.utils.datastructures import SortedDict
    1111
    12 from util import ValidationError, ErrorList
     12from util import ValidationError
    1313from forms import FormOptions, FormMetaclass, BaseForm
    1414from fields import Field, ChoiceField, EMPTY_VALUES
    1515from widgets import Select, SelectMultiple, MultipleHiddenInput
     
    221221        return new_class
    222222
    223223class BaseModelForm(BaseForm):
    224     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
    225                  initial=None, error_class=ErrorList, label_suffix=':',
    226                  instance=None):
     224    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, instance=None):
    227225        opts = self._meta
    228226        if instance is None:
    229227            # if we didn't get an instance, instantiate a new one
     
    235233        # if initial was provided, it should override the values from instance
    236234        if initial is not None:
    237235            object_data.update(initial)
    238         BaseForm.__init__(self, data, files, auto_id, prefix, object_data, error_class, label_suffix)
     236        BaseForm.__init__(self, data, files, auto_id, prefix, object_data)
    239237
    240238    def save(self, commit=True):
    241239        """
Back to Top