Code

Ticket #6631: 01-newforms-options.diff

File 01-newforms-options.diff, 9.3 KB (added by Petr Marhoun <petr.marhoun@…>, 6 years ago)
Line 
1=== modified file 'django/newforms/forms.py'
2--- django/newforms/forms.py    2008-02-18 14:55:31 +0000
3+++ django/newforms/forms.py    2008-02-09 00:13:55 +0000
4@@ -8,6 +8,7 @@
5 from django.utils.html import conditional_escape
6 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
7 from django.utils.safestring import mark_safe
8+from django.utils.text import capfirst
9 
10 from fields import Field, FileField
11 from widgets import TextInput, Textarea
12@@ -24,9 +25,19 @@
13 
14 class FormOptions(InheritableOptions):
15     _default_options = {
16+        # main options
17         'fieldsets': None,
18         'fields': None,
19         'exclude': None,
20+        # other options
21+        'error_class': ErrorList,
22+        'formfield_for_formfield': lambda self, formfield: formfield,
23+        'html_class_for_fields_with_errors': 'errors',
24+        'html_class_for_hidden_fields_row': 'hidden',
25+        'html_class_for_required_fields': 'required',
26+        'label_capitalization': True,
27+        'label_suffix': ':',
28+        'validation_order': None,
29     }
30 
31 class FormMetaclass(type):
32@@ -73,7 +84,7 @@
33             names = [name for name in new_cls._base_fields_pool if name not in new_cls._meta.exclude]
34         else:
35             names = new_cls._base_fields_pool.keys()
36-        new_cls.base_fields = SortedDict([(name, new_cls._base_fields_pool[name]) for name in names])
37+        new_cls.base_fields = SortedDict([(name, new_cls._meta.formfield_for_formfield(new_cls._meta, new_cls._base_fields_pool[name])) for name in names])
38     create_base_fields_from_base_fields_pool = classmethod(create_base_fields_from_base_fields_pool)
39 
40     def __new__(cls, name, bases, attrs):
41@@ -89,16 +100,13 @@
42     # class is different than Form. See the comments by the Form class for more
43     # information. Any improvements to the form API should be made to *this*
44     # 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=':'):
47+    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None):
48         self.is_bound = data is not None or files is not None
49         self.data = data or {}
50         self.files = files or {}
51         self.auto_id = auto_id
52         self.prefix = prefix
53         self.initial = initial or {}
54-        self.error_class = error_class
55-        self.label_suffix = label_suffix
56         self._errors = None # Stores the errors after clean() has been called.
57 
58         # The base_fields class attribute is the *class-wide* definition of
59@@ -186,7 +194,11 @@
60 
61     def hidden_fields_html_output(self, hidden_fields, hidden_fields_row):
62         "Helper function for outputting HTML from a hidden fields row. Used by _html_output."
63-        return hidden_fields_row % u''.join(hidden_fields)
64+        if self._meta.html_class_for_hidden_fields_row:
65+            attrs = u' class="%s"' % self._meta.html_class_for_hidden_fields_row
66+        else:
67+            attrs = u''
68+        return hidden_fields_row % (attrs, u''.join(hidden_fields))
69 
70     def _html_output(self, output_type, top_errors_row, fieldset_start, fieldset_end, hidden_fields_row):
71         "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
72@@ -221,15 +233,15 @@
73 
74     def as_table(self):
75         "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
76-        return self._html_output('table', u'<tr><td colspan="2">%s</td></tr>', u'%s\n<table>', u'</table>\n%s', u'<tr><td colspan="2">%s</td></tr>')
77+        return self._html_output('table', u'<tr><td colspan="2">%s</td></tr>', u'%s\n<table>', u'</table>\n%s', u'<tr%s><td colspan="2">%s</td></tr>')
78 
79     def as_ul(self):
80         "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
81-        return self._html_output('ul', u'<li>%s</li>', u'%s\n<ul>', u'</ul>\n%s', u'<li>%s</li>')
82+        return self._html_output('ul', u'<li>%s</li>', u'%s\n<ul>', u'</ul>\n%s', u'<li%s>%s</li>')
83 
84     def as_p(self):
85         "Returns this form rendered as HTML <p>s."
86-        return self._html_output('p', u'%s', u'%s', u'%s', u'<p>%s</p>')
87+        return self._html_output('p', u'%s', u'%s', u'%s', u'<p%s>%s</p>')
88 
89     def non_field_errors(self):
90         """
91@@ -237,7 +249,7 @@
92         field -- i.e., from Form.clean(). Returns an empty ErrorList if there
93         are none.
94         """
95-        return self.errors.get(NON_FIELD_ERRORS, self.error_class())
96+        return self.errors.get(NON_FIELD_ERRORS, self._meta.error_class())
97 
98     def full_clean(self):
99         """
100@@ -248,7 +260,11 @@
101         if not self.is_bound: # Stop further processing.
102             return
103         self.cleaned_data = {}
104-        for name, field in self.fields.items():
105+        if self._meta.validation_order:
106+            items = [(name, self.fields[name]) for name in self._meta.validation_order]
107+        else:
108+            items = self.fields.items()
109+        for name, field in items:
110             # value_from_datadict() gets the data from the data dictionaries.
111             # Each widget type knows how to retrieve its own data, because some
112             # widgets split data over several HTML fields.
113@@ -264,13 +280,13 @@
114                     value = getattr(self, 'clean_%s' % name)()
115                     self.cleaned_data[name] = value
116             except ValidationError, e:
117-                self._errors[name] = self.error_class(e.messages)
118+                self._errors[name] = self._meta.error_class(e.messages)
119                 if name in self.cleaned_data:
120                     del self.cleaned_data[name]
121         try:
122             self.cleaned_data = self.clean()
123         except ValidationError, e:
124-            self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
125+            self._errors[NON_FIELD_ERRORS] = self._meta.error_class(e.messages)
126         if self._errors:
127             delattr(self, 'cleaned_data')
128 
129@@ -321,7 +337,7 @@
130         Returns an ErrorList for this field. Returns an empty ErrorList
131         if there are none.
132         """
133-        return self.form.errors.get(self.name, self.form.error_class())
134+        return self.form.errors.get(self.name, self.form._meta.error_class())
135     errors = property(_errors)
136 
137     def as_widget(self, widget=None, attrs=None):
138@@ -372,16 +388,19 @@
139         if self.field.label is None:
140             return pretty_name(self.name)
141         else:
142-            return conditional_escape(force_unicode(self.field.label))
143+            label = conditional_escape(force_unicode(self.field.label))
144+            if self.form._meta.label_capitalization:
145+                label = capfirst(label)
146+            return label
147     label = property(_label)
148 
149     def _label_tag(self):
150         "Returns label tag for this field as safe HTML code."
151         label = self.label
152-        if self.form.label_suffix:
153+        if self.form._meta.label_suffix:
154             # Only add the suffix if the label does not end in punctuation.
155             if label and label[-1] not in ':?.!':
156-                label += self.form.label_suffix
157+                label += self.form._meta.label_suffix
158         id_ = self.widget.attrs.get('id') or self.auto_id
159         if label and id_:
160             id_ = self.widget.id_for_label(id_)
161@@ -400,7 +419,15 @@
162 
163     def _row_attrs(self):
164         "Returns row attributes for this field as safe HTML code."
165-        return flatatt(self.widget.row_attrs)
166+        attrs = self.widget.row_attrs.copy()
167+        class_list = attrs.pop('class', '').split()
168+        if self.form._meta.html_class_for_fields_with_errors and self.errors:
169+            class_list.append(self.form._meta.html_class_for_fields_with_errors)
170+        if self.form._meta.html_class_for_required_fields and self.field.required:
171+            class_list.append(self.form._meta.html_class_for_required_fields)
172+        if class_list:
173+            attrs['class'] = u' '.join(class_list)
174+        return flatatt(attrs)
175     row_attrs = property(_row_attrs)
176 
177     def _is_hidden(self):
178
179=== modified file 'django/newforms/models.py'
180--- django/newforms/models.py   2008-02-18 14:53:53 +0000
181+++ django/newforms/models.py   2008-02-18 15:00:59 +0000
182@@ -9,7 +9,7 @@
183 from django.utils.encoding import smart_unicode
184 from django.utils.datastructures import SortedDict, InheritableOptions
185 
186-from util import ValidationError, ErrorList
187+from util import ValidationError
188 from forms import FormOptions, FormMetaclass, BaseForm
189 from fields import Field, ChoiceField, EMPTY_VALUES
190 from widgets import Select, SelectMultiple, MultipleHiddenInput
191@@ -252,9 +252,7 @@
192         return new_cls
193 
194 class BaseModelForm(BaseForm):
195-    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
196-                 initial=None, error_class=ErrorList, label_suffix=':',
197-                 instance=None):
198+    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, instance=None):
199         opts = self._meta
200         if instance is None:
201             # if we didn't get an instance, instantiate a new one
202@@ -266,7 +264,7 @@
203         # if initial was provided, it should override the values from instance
204         if initial is not None:
205             object_data.update(initial)
206-        BaseForm.__init__(self, data, files, auto_id, prefix, object_data, error_class, label_suffix)
207+        BaseForm.__init__(self, data, files, auto_id, prefix, object_data)
208 
209     def save(self, commit=True):
210         """
211