Loading django/core/exceptions.py +46 −22 Original line number Diff line number Diff line Loading @@ -3,6 +3,9 @@ Global Django exception and warning classes. """ import logging from functools import reduce import operator from django.utils.encoding import force_text class DjangoRuntimeWarning(RuntimeWarning): Loading Loading @@ -74,46 +77,67 @@ NON_FIELD_ERRORS = '__all__' class ValidationError(Exception): """An error while validating data.""" def __init__(self, message, code=None, params=None): import operator from django.utils.encoding import force_text """ ValidationError can be passed any object that can be printed (usually a string), a list of objects or a dictionary. """ if isinstance(message, dict): self.message_dict = message # Reduce each list of messages into a single list. message = reduce(operator.add, message.values()) if isinstance(message, list): self.messages = [force_text(msg) for msg in message] self.error_dict = message elif isinstance(message, list): self.error_list = message else: self.code = code self.params = params self.message = message self.error_list = [self] @property def message_dict(self): message_dict = {} for field, messages in self.error_dict.items(): message_dict[field] = [] for message in messages: if isinstance(message, ValidationError): message_dict[field].extend(message.messages) else: message_dict[field].append(force_text(message)) return message_dict @property def messages(self): if hasattr(self, 'error_dict'): message_list = reduce(operator.add, self.error_dict.values()) else: message_list = self.error_list messages = [] for message in message_list: if isinstance(message, ValidationError): params = message.params message = message.message if params: message %= params message = force_text(message) else: message = force_text(message) self.messages = [message] messages.append(message) return messages def __str__(self): # This is needed because, without a __str__(), printing an exception # instance would result in this: # AttributeError: ValidationError instance has no attribute 'args' # See http://www.python.org/doc/current/tut/node10.html#handling if hasattr(self, 'message_dict'): if hasattr(self, 'error_dict'): return repr(self.message_dict) return repr(self.messages) def __repr__(self): if hasattr(self, 'message_dict'): return 'ValidationError(%s)' % repr(self.message_dict) return 'ValidationError(%s)' % repr(self.messages) return 'ValidationError(%s)' % self def update_error_dict(self, error_dict): if hasattr(self, 'message_dict'): if hasattr(self, 'error_dict'): if error_dict: for k, v in self.message_dict.items(): for k, v in self.error_dict.items(): error_dict.setdefault(k, []).extend(v) else: error_dict = self.message_dict error_dict = self.error_dict else: error_dict[NON_FIELD_ERRORS] = self.messages error_dict[NON_FIELD_ERRORS] = self.error_list return error_dict django/db/models/base.py +10 −9 Original line number Diff line number Diff line Loading @@ -910,7 +910,7 @@ class Model(six.with_metaclass(ModelBase)): 'field_label': six.text_type(field_labels) } def full_clean(self, exclude=None): def full_clean(self, exclude=None, validate_unique=True): """ Calls clean_fields, clean, and validate_unique, on the model, and raises a ``ValidationError`` for any errors that occurred. Loading @@ -932,6 +932,7 @@ class Model(six.with_metaclass(ModelBase)): errors = e.update_error_dict(errors) # Run unique checks, but only for fields that passed validation. if validate_unique: for name in errors.keys(): if name != NON_FIELD_ERRORS and name not in exclude: exclude.append(name) Loading Loading @@ -963,7 +964,7 @@ class Model(six.with_metaclass(ModelBase)): try: setattr(self, f.attname, f.clean(raw_value, self)) except ValidationError as e: errors[f.name] = e.messages errors[f.name] = e.error_list if errors: raise ValidationError(errors) Loading django/db/models/fields/__init__.py +3 −6 Original line number Diff line number Diff line Loading @@ -208,12 +208,9 @@ class Field(object): v(value) except exceptions.ValidationError as e: if hasattr(e, 'code') and e.code in self.error_messages: message = self.error_messages[e.code] if e.params: message = message % e.params errors.append(message) else: errors.extend(e.messages) e.message = self.error_messages[e.code] errors.extend(e.error_list) if errors: raise exceptions.ValidationError(errors) Loading django/forms/fields.py +3 −7 Original line number Diff line number Diff line Loading @@ -136,12 +136,8 @@ class Field(object): v(value) except ValidationError as e: if hasattr(e, 'code') and e.code in self.error_messages: message = self.error_messages[e.code] if e.params: message = message % e.params errors.append(message) else: errors.extend(e.messages) e.message = self.error_messages[e.code] errors.extend(e.error_list) if errors: raise ValidationError(errors) Loading Loading @@ -974,7 +970,7 @@ class MultiValueField(Field): # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. errors.extend(e.messages) errors.extend(e.error_list) if errors: raise ValidationError(errors) Loading django/forms/models.py +4 −10 Original line number Diff line number Diff line Loading @@ -389,17 +389,11 @@ class BaseModelForm(BaseForm): if isinstance(field, InlineForeignKeyField): exclude.append(f_name) # Clean the model instance's fields. try: self.instance.clean_fields(exclude=exclude) self.instance.full_clean(exclude=exclude, validate_unique=False) except ValidationError as e: self._update_errors(e.message_dict) # Call the model instance's clean method. try: self.instance.clean() except ValidationError as e: self._update_errors({NON_FIELD_ERRORS: e.messages}) self._update_errors(e) # Validate uniqueness if needed. if self._validate_unique: Loading @@ -414,7 +408,7 @@ class BaseModelForm(BaseForm): try: self.instance.validate_unique(exclude=exclude) except ValidationError as e: self._update_errors(e.message_dict) self._update_errors(e) def save(self, commit=True): """ Loading Loading
django/core/exceptions.py +46 −22 Original line number Diff line number Diff line Loading @@ -3,6 +3,9 @@ Global Django exception and warning classes. """ import logging from functools import reduce import operator from django.utils.encoding import force_text class DjangoRuntimeWarning(RuntimeWarning): Loading Loading @@ -74,46 +77,67 @@ NON_FIELD_ERRORS = '__all__' class ValidationError(Exception): """An error while validating data.""" def __init__(self, message, code=None, params=None): import operator from django.utils.encoding import force_text """ ValidationError can be passed any object that can be printed (usually a string), a list of objects or a dictionary. """ if isinstance(message, dict): self.message_dict = message # Reduce each list of messages into a single list. message = reduce(operator.add, message.values()) if isinstance(message, list): self.messages = [force_text(msg) for msg in message] self.error_dict = message elif isinstance(message, list): self.error_list = message else: self.code = code self.params = params self.message = message self.error_list = [self] @property def message_dict(self): message_dict = {} for field, messages in self.error_dict.items(): message_dict[field] = [] for message in messages: if isinstance(message, ValidationError): message_dict[field].extend(message.messages) else: message_dict[field].append(force_text(message)) return message_dict @property def messages(self): if hasattr(self, 'error_dict'): message_list = reduce(operator.add, self.error_dict.values()) else: message_list = self.error_list messages = [] for message in message_list: if isinstance(message, ValidationError): params = message.params message = message.message if params: message %= params message = force_text(message) else: message = force_text(message) self.messages = [message] messages.append(message) return messages def __str__(self): # This is needed because, without a __str__(), printing an exception # instance would result in this: # AttributeError: ValidationError instance has no attribute 'args' # See http://www.python.org/doc/current/tut/node10.html#handling if hasattr(self, 'message_dict'): if hasattr(self, 'error_dict'): return repr(self.message_dict) return repr(self.messages) def __repr__(self): if hasattr(self, 'message_dict'): return 'ValidationError(%s)' % repr(self.message_dict) return 'ValidationError(%s)' % repr(self.messages) return 'ValidationError(%s)' % self def update_error_dict(self, error_dict): if hasattr(self, 'message_dict'): if hasattr(self, 'error_dict'): if error_dict: for k, v in self.message_dict.items(): for k, v in self.error_dict.items(): error_dict.setdefault(k, []).extend(v) else: error_dict = self.message_dict error_dict = self.error_dict else: error_dict[NON_FIELD_ERRORS] = self.messages error_dict[NON_FIELD_ERRORS] = self.error_list return error_dict
django/db/models/base.py +10 −9 Original line number Diff line number Diff line Loading @@ -910,7 +910,7 @@ class Model(six.with_metaclass(ModelBase)): 'field_label': six.text_type(field_labels) } def full_clean(self, exclude=None): def full_clean(self, exclude=None, validate_unique=True): """ Calls clean_fields, clean, and validate_unique, on the model, and raises a ``ValidationError`` for any errors that occurred. Loading @@ -932,6 +932,7 @@ class Model(six.with_metaclass(ModelBase)): errors = e.update_error_dict(errors) # Run unique checks, but only for fields that passed validation. if validate_unique: for name in errors.keys(): if name != NON_FIELD_ERRORS and name not in exclude: exclude.append(name) Loading Loading @@ -963,7 +964,7 @@ class Model(six.with_metaclass(ModelBase)): try: setattr(self, f.attname, f.clean(raw_value, self)) except ValidationError as e: errors[f.name] = e.messages errors[f.name] = e.error_list if errors: raise ValidationError(errors) Loading
django/db/models/fields/__init__.py +3 −6 Original line number Diff line number Diff line Loading @@ -208,12 +208,9 @@ class Field(object): v(value) except exceptions.ValidationError as e: if hasattr(e, 'code') and e.code in self.error_messages: message = self.error_messages[e.code] if e.params: message = message % e.params errors.append(message) else: errors.extend(e.messages) e.message = self.error_messages[e.code] errors.extend(e.error_list) if errors: raise exceptions.ValidationError(errors) Loading
django/forms/fields.py +3 −7 Original line number Diff line number Diff line Loading @@ -136,12 +136,8 @@ class Field(object): v(value) except ValidationError as e: if hasattr(e, 'code') and e.code in self.error_messages: message = self.error_messages[e.code] if e.params: message = message % e.params errors.append(message) else: errors.extend(e.messages) e.message = self.error_messages[e.code] errors.extend(e.error_list) if errors: raise ValidationError(errors) Loading Loading @@ -974,7 +970,7 @@ class MultiValueField(Field): # Collect all validation errors in a single list, which we'll # raise at the end of clean(), rather than raising a single # exception for the first error we encounter. errors.extend(e.messages) errors.extend(e.error_list) if errors: raise ValidationError(errors) Loading
django/forms/models.py +4 −10 Original line number Diff line number Diff line Loading @@ -389,17 +389,11 @@ class BaseModelForm(BaseForm): if isinstance(field, InlineForeignKeyField): exclude.append(f_name) # Clean the model instance's fields. try: self.instance.clean_fields(exclude=exclude) self.instance.full_clean(exclude=exclude, validate_unique=False) except ValidationError as e: self._update_errors(e.message_dict) # Call the model instance's clean method. try: self.instance.clean() except ValidationError as e: self._update_errors({NON_FIELD_ERRORS: e.messages}) self._update_errors(e) # Validate uniqueness if needed. if self._validate_unique: Loading @@ -414,7 +408,7 @@ class BaseModelForm(BaseForm): try: self.instance.validate_unique(exclude=exclude) except ValidationError as e: self._update_errors(e.message_dict) self._update_errors(e) def save(self, commit=True): """ Loading