diff options
| author | Loic Bistuer <loic.bistuer@sixmedia.com> | 2013-11-30 02:38:13 +0700 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-12-16 16:33:28 -0500 |
| commit | 3ce9829b615336b0f3ac39b080c27fc8cf5af483 (patch) | |
| tree | def5d16f59f583bb20faf530b24e3f3d977fd458 /django | |
| parent | e2f142030b81a37e1c3187f5d336dcb6014fd1c0 (diff) | |
Fixed #17413 -- Serialization of form errors along with all metadata.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/admin/helpers.py | 2 | ||||
| -rw-r--r-- | django/forms/fields.py | 4 | ||||
| -rw-r--r-- | django/forms/forms.py | 4 | ||||
| -rw-r--r-- | django/forms/formsets.py | 2 | ||||
| -rw-r--r-- | django/forms/utils.py | 66 |
5 files changed, 61 insertions, 17 deletions
diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index 318c393c09..86ab0f263e 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -329,6 +329,8 @@ class AdminErrorList(forms.utils.ErrorList): Stores all errors for the form/formsets in an add/change stage view. """ def __init__(self, form, inline_formsets): + super(AdminErrorList, self).__init__() + if form.is_bound: self.extend(list(six.itervalues(form.errors))) for inline_formset in inline_formsets: diff --git a/django/forms/fields.py b/django/forms/fields.py index 6f88fb2662..fe056e3271 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -15,7 +15,7 @@ from io import BytesIO from django.core import validators from django.core.exceptions import ValidationError -from django.forms.utils import ErrorList, from_current_timezone, to_current_timezone +from django.forms.utils import from_current_timezone, to_current_timezone from django.forms.widgets import ( TextInput, NumberInput, EmailInput, URLInput, HiddenInput, MultipleHiddenInput, ClearableFileInput, CheckboxInput, Select, @@ -998,7 +998,7 @@ class MultiValueField(Field): DateField.clean(value[0]) and TimeField.clean(value[1]). """ clean_data = [] - errors = ErrorList() + errors = [] if not value or isinstance(value, (list, tuple)): if not value or not [v for v in value if v not in self.empty_values]: if self.required: diff --git a/django/forms/forms.py b/django/forms/forms.py index 350b8b8993..880a74f49e 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -321,9 +321,9 @@ class BaseForm(object): "argument contains errors for multiple fields." ) else: - error = dict(error) + error = error.error_dict else: - error = {field or NON_FIELD_ERRORS: list(error)} + error = {field or NON_FIELD_ERRORS: error.error_list} for field, error_list in error.items(): if field not in self.errors: diff --git a/django/forms/formsets.py b/django/forms/formsets.py index fd1fd92773..215ec1d876 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -341,7 +341,7 @@ class BaseFormSet(object): # Give self.clean() a chance to do cross-form validation. self.clean() except ValidationError as e: - self._non_form_errors = self.error_class(e.messages) + self._non_form_errors = self.error_class(e.error_list) def clean(self): """ diff --git a/django/forms/utils.py b/django/forms/utils.py index 9402f2612e..3582384293 100644 --- a/django/forms/utils.py +++ b/django/forms/utils.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals +import json +import sys import warnings from django.conf import settings @@ -8,12 +10,16 @@ from django.utils.encoding import force_text, python_2_unicode_compatible from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django.utils import six -import sys # Import ValidationError so that it can be imported from this # module to maintain backwards compatibility. from django.core.exceptions import ValidationError +try: + from collections import UserList +except ImportError: # Python 2 + from UserList import UserList + def flatatt(attrs): """ @@ -46,8 +52,12 @@ class ErrorDict(dict): The dictionary keys are the field names, and the values are the errors. """ - def __str__(self): - return self.as_ul() + def as_data(self): + return {f: e.as_data() for f, e in self.items()} + + def as_json(self): + errors = {f: json.loads(e.as_json()) for f, e in self.items()} + return json.dumps(errors) def as_ul(self): if not self: @@ -58,19 +68,35 @@ class ErrorDict(dict): ) def as_text(self): - return '\n'.join('* %s\n%s' % (k, '\n'.join(' * %s' % force_text(i) for i in v)) for k, v in self.items()) + output = [] + for field, errors in self.items(): + output.append('* %s' % field) + output.append('\n'.join(' * %s' % e for e in errors)) + return '\n'.join(output) + + def __str__(self): + return self.as_ul() @python_2_unicode_compatible -class ErrorList(list): +class ErrorList(UserList): """ A collection of errors that knows how to display itself in various formats. """ - def __str__(self): - return self.as_ul() + def as_data(self): + return self.data + + def as_json(self): + errors = [] + for error in ValidationError(self.data).error_list: + errors.append({ + 'message': list(error)[0], + 'code': error.code or '', + }) + return json.dumps(errors) def as_ul(self): - if not self: + if not self.data: return '' return format_html( '<ul class="errorlist">{0}</ul>', @@ -78,12 +104,28 @@ class ErrorList(list): ) def as_text(self): - if not self: - return '' - return '\n'.join('* %s' % force_text(e) for e in self) + return '\n'.join('* %s' % e for e in self) + + def __str__(self): + return self.as_ul() def __repr__(self): - return repr([force_text(e) for e in self]) + return repr(list(self)) + + def __contains__(self, item): + return item in list(self) + + def __eq__(self, other): + return list(self) == other + + def __ne__(self, other): + return list(self) != other + + def __getitem__(self, i): + error = self.data[i] + if isinstance(error, ValidationError): + return list(error)[0] + return force_text(error) # Utilities for time zone support in DateTimeField et al. |
