diff options
Diffstat (limited to 'django/forms')
| -rw-r--r-- | django/forms/fields.py | 96 | ||||
| -rw-r--r-- | django/forms/formsets.py | 9 | ||||
| -rw-r--r-- | django/forms/models.py | 32 | ||||
| -rw-r--r-- | django/forms/util.py | 13 |
4 files changed, 103 insertions, 47 deletions
diff --git a/django/forms/fields.py b/django/forms/fields.py index 219c82100e..52bcf9485c 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -125,7 +125,7 @@ class Field(object): def validate(self, value): if value in self.empty_values and self.required: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') def run_validators(self, value): if value in self.empty_values: @@ -246,7 +246,7 @@ class IntegerField(Field): try: value = int(str(value)) except (ValueError, TypeError): - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') return value def widget_attrs(self, widget): @@ -277,7 +277,7 @@ class FloatField(IntegerField): try: value = float(value) except (ValueError, TypeError): - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') return value def widget_attrs(self, widget): @@ -323,7 +323,7 @@ class DecimalField(IntegerField): try: value = Decimal(value) except DecimalException: - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') return value def validate(self, value): @@ -334,7 +334,7 @@ class DecimalField(IntegerField): # since it is never equal to itself. However, NaN is the only value that # isn't equal to itself, so we can use this to identify NaN if value != value or value == Decimal("Inf") or value == Decimal("-Inf"): - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') sign, digittuple, exponent = value.as_tuple() decimals = abs(exponent) # digittuple doesn't include any leading zeros. @@ -348,15 +348,24 @@ class DecimalField(IntegerField): whole_digits = digits - decimals if self.max_digits is not None and digits > self.max_digits: - raise ValidationError(self.error_messages['max_digits'] % { - 'max': self.max_digits}) + raise ValidationError( + self.error_messages['max_digits'], + code='max_digits', + params={'max': self.max_digits}, + ) if self.decimal_places is not None and decimals > self.decimal_places: - raise ValidationError(self.error_messages['max_decimal_places'] % { - 'max': self.decimal_places}) + raise ValidationError( + self.error_messages['max_decimal_places'], + code='max_decimal_places', + params={'max': self.decimal_places}, + ) if (self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places)): - raise ValidationError(self.error_messages['max_whole_digits'] % { - 'max': (self.max_digits - self.decimal_places)}) + raise ValidationError( + self.error_messages['max_whole_digits'], + code='max_whole_digits', + params={'max': (self.max_digits - self.decimal_places)}, + ) return value def widget_attrs(self, widget): @@ -391,7 +400,7 @@ class BaseTemporalField(Field): return self.strptime(value, format) except (ValueError, TypeError): continue - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') def strptime(self, value, format): raise NotImplementedError('Subclasses must define this method.') @@ -471,7 +480,7 @@ class DateTimeField(BaseTemporalField): # Input comes from a SplitDateTimeWidget, for example. So, it's two # components: date and time. if len(value) != 2: - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') if value[0] in self.empty_values and value[1] in self.empty_values: return None value = '%s %s' % tuple(value) @@ -548,22 +557,22 @@ class FileField(Field): file_name = data.name file_size = data.size except AttributeError: - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') if self.max_length is not None and len(file_name) > self.max_length: - error_values = {'max': self.max_length, 'length': len(file_name)} - raise ValidationError(self.error_messages['max_length'] % error_values) + params = {'max': self.max_length, 'length': len(file_name)} + raise ValidationError(self.error_messages['max_length'], code='max_length', params=params) if not file_name: - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') if not self.allow_empty_file and not file_size: - raise ValidationError(self.error_messages['empty']) + raise ValidationError(self.error_messages['empty'], code='empty') return data def clean(self, data, initial=None): # If the widget got contradictory inputs, we raise a validation error if data is FILE_INPUT_CONTRADICTION: - raise ValidationError(self.error_messages['contradiction']) + raise ValidationError(self.error_messages['contradiction'], code='contradiction') # False means the field value should be cleared; further validation is # not needed. if data is False: @@ -623,7 +632,10 @@ class ImageField(FileField): Image.open(file).verify() except Exception: # Pillow (or PIL) doesn't recognize it as an image. - six.reraise(ValidationError, ValidationError(self.error_messages['invalid_image']), sys.exc_info()[2]) + six.reraise(ValidationError, ValidationError( + self.error_messages['invalid_image'], + code='invalid_image', + ), sys.exc_info()[2]) if hasattr(f, 'seek') and callable(f.seek): f.seek(0) return f @@ -648,7 +660,7 @@ class URLField(CharField): except ValueError: # urlparse.urlsplit can raise a ValueError with some # misformatted URLs. - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') value = super(URLField, self).to_python(value) if value: @@ -692,7 +704,7 @@ class BooleanField(Field): def validate(self, value): if not value and self.required: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') def _has_changed(self, initial, data): # Sometimes data or initial could be None or '' which should be the @@ -776,7 +788,11 @@ class ChoiceField(Field): """ super(ChoiceField, self).validate(value) if value and not self.valid_value(value): - raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) + raise ValidationError( + self.error_messages['invalid_choice'], + code='invalid_choice', + params={'value': value}, + ) def valid_value(self, value): "Check to see if the provided value is a valid choice" @@ -810,7 +826,11 @@ class TypedChoiceField(ChoiceField): try: value = self.coerce(value) except (ValueError, TypeError, ValidationError): - raise ValidationError(self.error_messages['invalid_choice'] % {'value': value}) + raise ValidationError( + self.error_messages['invalid_choice'], + code='invalid_choice', + params={'value': value}, + ) return value @@ -826,7 +846,7 @@ class MultipleChoiceField(ChoiceField): if not value: return [] elif not isinstance(value, (list, tuple)): - raise ValidationError(self.error_messages['invalid_list']) + raise ValidationError(self.error_messages['invalid_list'], code='invalid_list') return [smart_text(val) for val in value] def validate(self, value): @@ -834,11 +854,15 @@ class MultipleChoiceField(ChoiceField): Validates that the input is a list or tuple. """ if self.required and not value: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') # Validate that each value in the value list is in self.choices. for val in value: if not self.valid_value(val): - raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) + raise ValidationError( + self.error_messages['invalid_choice'], + code='invalid_choice', + params={'value': val}, + ) def _has_changed(self, initial, data): if initial is None: @@ -871,14 +895,18 @@ class TypedMultipleChoiceField(MultipleChoiceField): try: new_value.append(self.coerce(choice)) except (ValueError, TypeError, ValidationError): - raise ValidationError(self.error_messages['invalid_choice'] % {'value': choice}) + raise ValidationError( + self.error_messages['invalid_choice'], + code='invalid_choice', + params={'value': choice}, + ) return new_value def validate(self, value): if value != self.empty_value: super(TypedMultipleChoiceField, self).validate(value) elif self.required: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') class ComboField(Field): @@ -952,18 +980,18 @@ class MultiValueField(Field): 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: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') else: return self.compress([]) else: - raise ValidationError(self.error_messages['invalid']) + raise ValidationError(self.error_messages['invalid'], code='invalid') for i, field in enumerate(self.fields): try: field_value = value[i] except IndexError: field_value = None if self.required and field_value in self.empty_values: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') try: clean_data.append(field.clean(field_value)) except ValidationError as e: @@ -1078,9 +1106,9 @@ class SplitDateTimeField(MultiValueField): # Raise a validation error if time or date is empty # (possible if SplitDateTimeField has required=False). if data_list[0] in self.empty_values: - raise ValidationError(self.error_messages['invalid_date']) + raise ValidationError(self.error_messages['invalid_date'], code='invalid_date') if data_list[1] in self.empty_values: - raise ValidationError(self.error_messages['invalid_time']) + raise ValidationError(self.error_messages['invalid_time'], code='invalid_time') result = datetime.datetime.combine(*data_list) return from_current_timezone(result) return None diff --git a/django/forms/formsets.py b/django/forms/formsets.py index 79e1c2298a..edd362c595 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -85,7 +85,10 @@ class BaseFormSet(object): if self.is_bound: form = ManagementForm(self.data, auto_id=self.auto_id, prefix=self.prefix) if not form.is_valid(): - raise ValidationError('ManagementForm data is missing or has been tampered with') + raise ValidationError( + _('ManagementForm data is missing or has been tampered with'), + code='missing_management_form', + ) else: form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={ TOTAL_FORM_COUNT: self.total_form_count(), @@ -315,7 +318,9 @@ class BaseFormSet(object): self.management_form.cleaned_data[TOTAL_FORM_COUNT] > self.absolute_max: raise ValidationError(ungettext( "Please submit %d or fewer forms.", - "Please submit %d or fewer forms.", self.max_num) % self.max_num) + "Please submit %d or fewer forms.", self.max_num) % self.max_num, + code='too_many_forms', + ) # Give self.clean() a chance to do cross-form validation. self.clean() except ValidationError as e: diff --git a/django/forms/models.py b/django/forms/models.py index c4070b97fe..821f64199b 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -314,7 +314,17 @@ class BaseModelForm(BaseForm): super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data, error_class, label_suffix, empty_permitted) - def _update_errors(self, message_dict): + def _update_errors(self, errors): + for field, messages in errors.error_dict.items(): + if field not in self.fields: + continue + field = self.fields[field] + for message in messages: + if isinstance(message, ValidationError): + if message.code in field.error_messages: + message.message = field.error_messages[message.code] + + message_dict = errors.message_dict for k, v in message_dict.items(): if k != NON_FIELD_ERRORS: self._errors.setdefault(k, self.error_class()).extend(v) @@ -1000,7 +1010,7 @@ class InlineForeignKeyField(Field): else: orig = self.parent_instance.pk if force_text(value) != force_text(orig): - raise ValidationError(self.error_messages['invalid_choice']) + raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice') return self.parent_instance def _has_changed(self, initial, data): @@ -1115,7 +1125,7 @@ class ModelChoiceField(ChoiceField): key = self.to_field_name or 'pk' value = self.queryset.get(**{key: value}) except (ValueError, self.queryset.model.DoesNotExist): - raise ValidationError(self.error_messages['invalid_choice']) + raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice') return value def validate(self, value): @@ -1150,22 +1160,30 @@ class ModelMultipleChoiceField(ModelChoiceField): def clean(self, value): if self.required and not value: - raise ValidationError(self.error_messages['required']) + raise ValidationError(self.error_messages['required'], code='required') elif not self.required and not value: return self.queryset.none() if not isinstance(value, (list, tuple)): - raise ValidationError(self.error_messages['list']) + raise ValidationError(self.error_messages['list'], code='list') key = self.to_field_name or 'pk' for pk in value: try: self.queryset.filter(**{key: pk}) except ValueError: - raise ValidationError(self.error_messages['invalid_pk_value'] % {'pk': pk}) + raise ValidationError( + self.error_messages['invalid_pk_value'], + code='invalid_pk_value', + params={'pk': pk}, + ) qs = self.queryset.filter(**{'%s__in' % key: value}) pks = set([force_text(getattr(o, key)) for o in qs]) for val in value: if force_text(val) not in pks: - raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) + raise ValidationError( + self.error_messages['invalid_choice'], + code='invalid_choice', + params={'value': val}, + ) # Since this overrides the inherited ModelChoiceField.clean # we run custom validators here self.run_validators(value) diff --git a/django/forms/util.py b/django/forms/util.py index f1b864e6b3..568cdd1086 100644 --- a/django/forms/util.py +++ b/django/forms/util.py @@ -80,12 +80,17 @@ def from_current_timezone(value): try: return timezone.make_aware(value, current_timezone) except Exception: - msg = _( + message = _( '%(datetime)s couldn\'t be interpreted ' 'in time zone %(current_timezone)s; it ' - 'may be ambiguous or it may not exist.') % {'datetime': value, 'current_timezone': - current_timezone} - six.reraise(ValidationError, ValidationError(msg), sys.exc_info()[2]) + 'may be ambiguous or it may not exist.' + ) + params = {'datetime': value, 'current_timezone': current_timezone} + six.reraise(ValidationError, ValidationError( + message, + code='ambiguous_timezone', + params=params, + ), sys.exc_info()[2]) return value def to_current_timezone(value): |
