Improved error message display during validation errors.
When reporting a validation error (during model validation or fixture loading, for example), the error messages now report the bad value as well as the expected type. This can make identifying the offending field and problem a bit easier. Fixed #11595. Patch from raulcd and wildfire with supervision from Russell. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16638 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d661cc5e3a
commit
c471d471bf
|
@ -462,7 +462,7 @@ class AutoField(Field):
|
||||||
|
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u'This value must be an integer.'),
|
'invalid': _(u"'%s' value must be an integer."),
|
||||||
}
|
}
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__
|
assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__
|
||||||
|
@ -478,7 +478,8 @@ class AutoField(Field):
|
||||||
try:
|
try:
|
||||||
return int(value)
|
return int(value)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def validate(self, value, model_instance):
|
def validate(self, value, model_instance):
|
||||||
pass
|
pass
|
||||||
|
@ -500,7 +501,7 @@ class AutoField(Field):
|
||||||
class BooleanField(Field):
|
class BooleanField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u'This value must be either True or False.'),
|
'invalid': _(u"'%s' value must be either True or False."),
|
||||||
}
|
}
|
||||||
description = _("Boolean (Either True or False)")
|
description = _("Boolean (Either True or False)")
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -521,7 +522,8 @@ class BooleanField(Field):
|
||||||
return True
|
return True
|
||||||
if value in ('f', 'False', '0'):
|
if value in ('f', 'False', '0'):
|
||||||
return False
|
return False
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def get_prep_lookup(self, lookup_type, value):
|
def get_prep_lookup(self, lookup_type, value):
|
||||||
# Special-case handling for filters coming from a Web request (e.g. the
|
# Special-case handling for filters coming from a Web request (e.g. the
|
||||||
|
@ -753,7 +755,7 @@ class DateTimeField(DateField):
|
||||||
class DecimalField(Field):
|
class DecimalField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u'This value must be a decimal number.'),
|
'invalid': _(u"'%s' value must be a decimal number."),
|
||||||
}
|
}
|
||||||
description = _("Decimal number")
|
description = _("Decimal number")
|
||||||
|
|
||||||
|
@ -770,7 +772,8 @@ class DecimalField(Field):
|
||||||
try:
|
try:
|
||||||
return decimal.Decimal(value)
|
return decimal.Decimal(value)
|
||||||
except decimal.InvalidOperation:
|
except decimal.InvalidOperation:
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def _format(self, value):
|
def _format(self, value):
|
||||||
if isinstance(value, basestring) or value is None:
|
if isinstance(value, basestring) or value is None:
|
||||||
|
@ -848,7 +851,7 @@ class FilePathField(Field):
|
||||||
class FloatField(Field):
|
class FloatField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _("This value must be a float."),
|
'invalid': _("'%s' value must be a float."),
|
||||||
}
|
}
|
||||||
description = _("Floating point number")
|
description = _("Floating point number")
|
||||||
|
|
||||||
|
@ -866,7 +869,8 @@ class FloatField(Field):
|
||||||
try:
|
try:
|
||||||
return float(value)
|
return float(value)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.FloatField}
|
defaults = {'form_class': forms.FloatField}
|
||||||
|
@ -876,7 +880,7 @@ class FloatField(Field):
|
||||||
class IntegerField(Field):
|
class IntegerField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _("This value must be an integer."),
|
'invalid': _("'%s' value must be an integer."),
|
||||||
}
|
}
|
||||||
description = _("Integer")
|
description = _("Integer")
|
||||||
|
|
||||||
|
@ -900,7 +904,8 @@ class IntegerField(Field):
|
||||||
try:
|
try:
|
||||||
return int(value)
|
return int(value)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
defaults = {'form_class': forms.IntegerField}
|
defaults = {'form_class': forms.IntegerField}
|
||||||
|
@ -981,7 +986,7 @@ class GenericIPAddressField(Field):
|
||||||
class NullBooleanField(Field):
|
class NullBooleanField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _("This value must be either None, True or False."),
|
'invalid': _("'%s' value must be either None, True or False."),
|
||||||
}
|
}
|
||||||
description = _("Boolean (Either True, False or None)")
|
description = _("Boolean (Either True, False or None)")
|
||||||
|
|
||||||
|
@ -1004,7 +1009,8 @@ class NullBooleanField(Field):
|
||||||
return True
|
return True
|
||||||
if value in ('f', 'False', '0'):
|
if value in ('f', 'False', '0'):
|
||||||
return False
|
return False
|
||||||
raise exceptions.ValidationError(self.error_messages['invalid'])
|
msg = self.error_messages['invalid'] % str(value)
|
||||||
|
raise exceptions.ValidationError(msg)
|
||||||
|
|
||||||
def get_prep_lookup(self, lookup_type, value):
|
def get_prep_lookup(self, lookup_type, value):
|
||||||
# Special-case handling for filters coming from a Web request (e.g. the
|
# Special-case handling for filters coming from a Web request (e.g. the
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.utils.unittest import TestCase
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationMessagesTest(TestCase):
|
||||||
|
|
||||||
|
def test_autofield_field_raises_error_message(self):
|
||||||
|
f = models.AutoField(primary_key=True)
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages, [u"'foo' value must be an integer."])
|
||||||
|
|
||||||
|
def test_integer_field_raises_error_message(self):
|
||||||
|
f = models.IntegerField()
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages, [u"'foo' value must be an integer."])
|
||||||
|
|
||||||
|
def test_boolean_field_raises_error_message(self):
|
||||||
|
f = models.BooleanField()
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages,
|
||||||
|
[u"'foo' value must be either True or False."])
|
||||||
|
|
||||||
|
def test_float_field_raises_error_message(self):
|
||||||
|
f = models.FloatField()
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages, [u"'foo' value must be a float."])
|
||||||
|
|
||||||
|
def test_decimal_field_raises_error_message(self):
|
||||||
|
f = models.DecimalField()
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages,
|
||||||
|
[u"'foo' value must be a decimal number."])
|
||||||
|
|
||||||
|
def test_null_boolean_field_raises_error_message(self):
|
||||||
|
f = models.NullBooleanField()
|
||||||
|
self.assertRaises(ValidationError, f.clean, 'foo', None)
|
||||||
|
try:
|
||||||
|
f.clean('foo', None)
|
||||||
|
except ValidationError, e:
|
||||||
|
self.assertEqual(e.messages,
|
||||||
|
[u"'foo' value must be either None, True or False."])
|
Loading…
Reference in New Issue