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

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

    === modified file 'django/forms/forms.py'
     
    33"""
    44
    55from copy import deepcopy
     6import re
    67
    78from django.utils.html import conditional_escape
    89from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
    910from django.utils.safestring import mark_safe
     11from django.utils.text import capfirst
    1012
    1113from fields import FileField
    1214from widgets import Media, TextInput, Textarea
     
    2426
    2527class FormOptions(object):
    2628    def __init__(self, options=None):
     29        # main options
    2730        self.fieldsets = getattr(options, 'fieldsets', None)
    2831        self.fields = getattr(options, 'fields', None)
    2932        self.exclude = getattr(options, 'exclude', None)
     33        # other options
     34        self.error_class = getattr(options, 'error_class', ErrorList)
     35        self.error_row_class = getattr(options, 'error_row_class', 'error')
     36        # self.error_row_class = getattr(options, 'error_row_class', None) # backward-compatible
     37        self.hidden_row_class = getattr(options, 'hidden_row_class', 'hidden')
     38        self.label_capfirst = getattr(options, 'label_capfirst', True)
     39        # self.label_capfirst = getattr(options, 'label_capfirst', False) # backward-compatible
     40        self.label_suffix = getattr(options, 'label_suffix', ':')
     41        self.required_row_class = getattr(options, 'required_row_class', 'required')
     42        # self.required_row_class = getattr(options, 'required_row_class', None) # backward-compatible
     43        self.use_field_row_class = getattr(options, 'use_field_row_class', True)
     44        # self.use_field_row_class = getattr(options, 'use_field_row_class', False) # backward-compatible
    3045
    3146class FormMetaclass(type):
    3247    def __new__(cls, name, bases, attrs):
     
    4459    # information. Any improvements to the form API should be made to *this*
    4560    # class, not to the Form class.
    4661    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
    47                  initial=None, error_class=ErrorList, label_suffix=':',
     62                 initial=None, error_class=None, label_suffix=None,
    4863                 empty_permitted=False):
    4964        self.is_bound = data is not None or files is not None
    5065        self.data = data or {}
     
    5267        self.auto_id = auto_id
    5368        self.prefix = prefix
    5469        self.initial = initial or {}
    55         self.error_class = error_class
    56         self.label_suffix = label_suffix
     70        if not hasattr(self, '_meta'):
     71            self._options = FormOptions
     72            metaclassing.create_meta(self, {})
     73        if error_class is not None:
     74            self.error_class = error_class
     75        if label_suffix is not None:
     76            self.label_suffix = label_suffix
    5777        self.empty_permitted = empty_permitted
    5878        self._errors = None # Stores the errors after clean() has been called.
    5979        self._changed_data = None
     
    152172            'help_text': self._help_text_html_output(bf, help_text_html),
    153173            'attrs': bf.row_attrs,
    154174        }
     175   
     176    _field_row_class_re = re.compile(r'([a-z])([A-Z])')
     177    def _field_row_class(self, field):
     178        return (self._field_row_class_re.sub(r'\1-\2', field.__class__.__name__).lower() +
     179            ' ' + self._field_row_class_re.sub(r'\1-\2', field.widget.__class__.__name__).lower())
    155180
    156181    def _top_errors_html_output(self, top_errors, top_errors_html):
    157182        "Helper function for outputting HTML from a top errors. Used by _html_output."
     
    182207
    183208    def _hidden_fields_html_output(self, hidden_fields, hidden_fields_html):
    184209        "Helper function for outputting HTML from a hidden fields. Used by _html_output."
     210        if self.hidden_row_class:
     211            attrs = u' class="%s"' % self.hidden_row_class
     212        else:
     213            attrs = u''
    185214        return hidden_fields_html % {
     215            'attrs': attrs,
    186216            'hidden_fields': u''.join(hidden_fields),
    187217        }
    188218
     
    226256            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<table>',
    227257            'fieldset_end_html': u'</table>\n</fieldset>',
    228258            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    229             'hidden_fields_html': u'<tr class="hidden"><td colspan="2">%(hidden_fields)s</td></tr>',
     259            'hidden_fields_html': u'<tr%(attrs)s><td colspan="2">%(hidden_fields)s</td></tr>',
    230260        }
    231261        return self._html_output(**kwargs)
    232262
     
    240270            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s<ul>',
    241271            'fieldset_end_html': u'</ul>\n</fieldset>',
    242272            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    243             'hidden_fields_html': u'<li class="hidden">%(hidden_fields)s</li>',
     273            'hidden_fields_html': u'<li%(attrs)s>%(hidden_fields)s</li>',
    244274        }
    245275        return self._html_output(**kwargs)
    246276
     
    254284            'fieldset_start_html': u'<fieldset%(attrs)s>\n%(legend_tag)s',
    255285            'fieldset_end_html': u'</fieldset>',
    256286            'legend_tag_html': u'<legend>%(legend)s</legend>\n',
    257             'hidden_fields_html': u'<p class="hidden">%(hidden_fields)s</p>',
     287            'hidden_fields_html': u'<p%(attrs)s>%(hidden_fields)s</p>',
    258288        }
    259289        return self._html_output(**kwargs)
    260290
     
    439469        if self.field.label is None:
    440470            return pretty_name(self.name)
    441471        else:
    442             return conditional_escape(force_unicode(self.field.label))
     472            label = conditional_escape(force_unicode(self.field.label))
     473            if self.form.label_capfirst:
     474                label = capfirst(label)
     475            return label
    443476    label = property(_label)
    444477
    445478    def _label_id(self):
     
    459492
    460493    def _row_attrs(self):
    461494        "Returns row attributes for this field as safe HTML."
    462         return flatatt(self.widget.row_attrs)
     495        attrs = self.widget.row_attrs.copy()
     496        class_list = attrs.pop('class', '').split()
     497        if self.form.error_row_class and self.errors:
     498            class_list.append(self.form.error_row_class)
     499        if self.form.required_row_class and self.required:
     500            class_list.append(self.form.required_row_class)
     501        if self.form.use_field_row_class:
     502            class_list.append(self.form._field_row_class(self.field))
     503        if class_list:
     504            attrs['class'] = u' '.join(class_list)
     505        return flatatt(attrs)
    463506    row_attrs = property(_row_attrs)
    464507
    465508    def label_tag(self, contents=None, attrs=None):
  • django/forms/metaclassing.py

    === modified file 'django/forms/metaclassing.py'
     
    1010
    1111def create_meta(cls, attrs):
    1212    cls._meta = cls._options(getattr(cls, 'Meta', None))
     13    for name, attr in cls._meta.__dict__.items():
     14        if name not in ('fieldsets', 'fields', 'exclude'):
     15            setattr(cls, name, attr)
    1316
    1417def create_declared_fields(cls, attrs):
    1518    fields = []
     
    2326def create_model_fields(cls, attrs):
    2427    formfield_callback = attrs.pop('formfield_callback', lambda f: f.formfield())
    2528    fields = []
    26     if cls._meta.model:
    27         for dbfield in cls._meta.model._meta.fields + cls._meta.model._meta.many_to_many:
     29    if cls.model:
     30        for dbfield in cls.model._meta.fields + cls.model._meta.many_to_many:
    2831            if dbfield.editable:
    2932                formfield = formfield_callback(dbfield)
    3033                if formfield:
     
    4548    for base in cls.__mro__[::-1]:
    4649        try:
    4750            declared_fields += base.declared_fields.items()
    48             if base._meta.model:
     51            if base.model:
    4952                model_fields = base.model_fields.items()
    5053        except AttributeError:
    5154            pass
  • django/forms/models.py

    === modified file 'django/forms/models.py'
     
    77from django.utils.encoding import smart_unicode
    88from django.utils.datastructures import SortedDict
    99
    10 from util import ValidationError, ErrorList
     10from util import ValidationError
    1111from forms import FormOptions, FormMetaclass, BaseForm
    1212from fields import Field, ChoiceField, IntegerField, EMPTY_VALUES
    1313from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput
     
    165165
    166166class BaseModelForm(BaseForm):
    167167    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
    168                  initial=None, error_class=ErrorList, label_suffix=':',
     168                 initial=None, error_class=None, label_suffix=None,
    169169                 empty_permitted=False, instance=None):
    170170        opts = self._meta
    171171        if instance is None:
Back to Top