diff --git a/django/newforms/forms.py b/django/newforms/forms.py
index 2c481e4..fb9bdb9 100644
a
|
b
|
class BaseForm(StrAndUnicode):
|
64 | 64 | # information. Any improvements to the form API should be made to *this* |
65 | 65 | # class, not to the Form class. |
66 | 66 | def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, |
67 | | initial=None, error_class=ErrorList, label_suffix=':'): |
| 67 | initial=None, error_list=ErrorList, error_dict=ErrorDict, label_suffix=':'): |
68 | 68 | self.is_bound = data is not None or files is not None |
69 | 69 | self.data = data or {} |
70 | 70 | self.files = files or {} |
71 | 71 | self.auto_id = auto_id |
72 | 72 | self.prefix = prefix |
73 | 73 | self.initial = initial or {} |
74 | | self.error_class = error_class |
| 74 | self.error_list = error_list |
| 75 | self.error_dict = error_dict |
75 | 76 | self.label_suffix = label_suffix |
76 | 77 | self._errors = None # Stores the errors after clean() has been called. |
77 | 78 | |
… |
… |
class BaseForm(StrAndUnicode):
|
126 | 127 | output, hidden_fields = [], [] |
127 | 128 | for name, field in self.fields.items(): |
128 | 129 | bf = BoundField(self, field, name) |
129 | | bf_errors = self.error_class([escape(error) for error in bf.errors]) # Escape and cache in local variable. |
| 130 | bf_errors = bf.errors # Escape and cache in local variable. |
130 | 131 | if bf.is_hidden: |
131 | 132 | if bf_errors: |
132 | 133 | top_errors.extend([u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors]) |
… |
… |
class BaseForm(StrAndUnicode):
|
182 | 183 | field -- i.e., from Form.clean(). Returns an empty ErrorList if there |
183 | 184 | are none. |
184 | 185 | """ |
185 | | return self.errors.get(NON_FIELD_ERRORS, self.error_class()) |
| 186 | return self.errors.get(NON_FIELD_ERRORS, self.error_list()) |
186 | 187 | |
187 | 188 | def full_clean(self): |
188 | 189 | """ |
189 | 190 | Cleans all of self.data and populates self._errors and |
190 | 191 | self.cleaned_data. |
191 | 192 | """ |
192 | | self._errors = ErrorDict() |
| 193 | self._errors = self.error_dict(error_list=self.error_list) |
193 | 194 | if not self.is_bound: # Stop further processing. |
194 | 195 | return |
195 | 196 | self.cleaned_data = {} |
… |
… |
class BaseForm(StrAndUnicode):
|
209 | 210 | value = getattr(self, 'clean_%s' % name)() |
210 | 211 | self.cleaned_data[name] = value |
211 | 212 | except ValidationError, e: |
212 | | self._errors[name] = e.messages |
| 213 | self._errors[name] = (field.label, e.messages) |
213 | 214 | if name in self.cleaned_data: |
214 | 215 | del self.cleaned_data[name] |
215 | 216 | try: |
216 | 217 | self.cleaned_data = self.clean() |
217 | 218 | except ValidationError, e: |
218 | | self._errors[NON_FIELD_ERRORS] = e.messages |
| 219 | self._errors[NON_FIELD_ERRORS] = (u'', e.messages) |
219 | 220 | if self._errors: |
220 | 221 | delattr(self, 'cleaned_data') |
221 | 222 | |
… |
… |
class BoundField(StrAndUnicode):
|
269 | 270 | Returns an ErrorList for this field. Returns an empty ErrorList |
270 | 271 | if there are none. |
271 | 272 | """ |
272 | | return self.form.errors.get(self.name, self.form.error_class()) |
| 273 | return self.form.errors.get(self.name, self.form.error_list()) |
273 | 274 | errors = property(_errors) |
274 | 275 | |
275 | 276 | def as_widget(self, widget=None, attrs=None): |
diff --git a/django/newforms/util.py b/django/newforms/util.py
index b3edf41..55ce614 100644
a
|
b
|
def flatatt(attrs):
|
12 | 12 | """ |
13 | 13 | return u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()]) |
14 | 14 | |
15 | | class ErrorDict(dict, StrAndUnicode): |
| 15 | class ErrorList(list, StrAndUnicode): |
16 | 16 | """ |
17 | 17 | A collection of errors that knows how to display itself in various formats. |
18 | | |
19 | | The dictionary keys are the field names, and the values are the errors. |
20 | 18 | """ |
21 | 19 | def __unicode__(self): |
22 | 20 | return self.as_ul() |
… |
… |
class ErrorDict(dict, StrAndUnicode):
|
24 | 22 | def as_ul(self): |
25 | 23 | if not self: return u'' |
26 | 24 | return mark_safe(u'<ul class="errorlist">%s</ul>' |
27 | | % ''.join([u'<li>%s%s</li>' % (k, force_unicode(v)) |
28 | | for k, v in self.items()])) |
| 25 | % ''.join([u'<li>%s</li>' % escape(smart_unicode(e)) for e in self])) |
29 | 26 | |
30 | 27 | def as_text(self): |
31 | | return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % force_unicode(i) for i in v])) for k, v in self.items()]) |
| 28 | if not self: return u'' |
| 29 | return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) |
32 | 30 | |
33 | | class ErrorList(list, StrAndUnicode): |
| 31 | def __repr__(self): |
| 32 | return repr([force_unicode(e) for e in self]) |
| 33 | |
| 34 | class ErrorDict(dict, StrAndUnicode): |
34 | 35 | """ |
35 | 36 | A collection of errors that knows how to display itself in various formats. |
| 37 | |
| 38 | The dictionary keys are the field names, and the values are the errors. |
36 | 39 | """ |
| 40 | def __init__(self, error_list=ErrorList): |
| 41 | self.error_list = error_list |
| 42 | |
37 | 43 | def __unicode__(self): |
38 | 44 | return self.as_ul() |
39 | 45 | |
| 46 | def __getitem__(self, key): |
| 47 | value = super(ErrorDict, self).__getitem__(key) |
| 48 | if value: |
| 49 | return self.error_list(value[1]) |
| 50 | return self.error_list() |
| 51 | |
| 52 | def get(self, key, default=None): |
| 53 | value = super(ErrorDict, self).get(key, default) |
| 54 | if value: |
| 55 | return self.error_list(value[1]) |
| 56 | return self.error_list() |
| 57 | |
40 | 58 | def as_ul(self): |
41 | 59 | if not self: return u'' |
42 | 60 | return mark_safe(u'<ul class="errorlist">%s</ul>' |
43 | | % ''.join([u'<li>%s</li>' % force_unicode(e) for e in self])) |
| 61 | % ''.join([u'<li>%s%s</li>' % (v[0] and escape(force_unicode(v[0])) or k, force_unicode(self.error_list(v[1]))) |
| 62 | for k, v in self.items()])) |
44 | 63 | |
45 | 64 | def as_text(self): |
46 | | if not self: return u'' |
47 | | return u'\n'.join([u'* %s' % force_unicode(e) for e in self]) |
| 65 | return u'\n'.join([u'* %s\n%s' % (v[0] and force_unicode(v[0]) or k, u'\n'.join([u' * %s' % force_unicode(i) for i in v[1]])) for k, v in self.items()]) |
48 | 66 | |
49 | 67 | def __repr__(self): |
50 | | return repr([force_unicode(e) for e in self]) |
| 68 | return repr(dict([(k, v[1]) for k, v in self.items()])) |
51 | 69 | |
52 | 70 | class ValidationError(Exception): |
53 | 71 | def __init__(self, message): |
diff --git a/django/test/_doctest.py b/django/test/_doctest.py
index a56483c..6d66a8d 100644
a
|
b
|
class DocTest:
|
503 | 503 | self.globs = globs.copy() |
504 | 504 | self.name = name |
505 | 505 | self.filename = filename |
506 | | self.lineno = lineno |
| 506 | self.lineno = lineno or 0 |
507 | 507 | |
508 | 508 | def __repr__(self): |
509 | 509 | if len(self.examples) == 0: |
diff --git a/tests/regressiontests/forms/extra.py b/tests/regressiontests/forms/extra.py
index 9dff407..6b29324 100644
a
|
b
|
u'sirrobin'
|
369 | 369 | ... email = EmailField() |
370 | 370 | ... comment = CharField() |
371 | 371 | >>> data = dict(email='invalid') |
372 | | >>> f = CommentForm(data, auto_id=False, error_class=DivErrorList) |
| 372 | >>> f = CommentForm(data, auto_id=False, error_list=DivErrorList) |
373 | 373 | >>> print f.as_p() |
374 | 374 | <p>Name: <input type="text" name="name" maxlength="50" /></p> |
375 | 375 | <div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> |