Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit c471d471bf9cb4f8da1fad78c5037660186ba6fd 1 parent d661cc5
Malcolm Tredinnick malcolmt authored
30 django/db/models/fields/__init__.py
View
@@ -462,7 +462,7 @@ class AutoField(Field):
empty_strings_allowed = False
default_error_messages = {
- 'invalid': _(u'This value must be an integer.'),
+ 'invalid': _(u"'%s' value must be an integer."),
}
def __init__(self, *args, **kwargs):
assert kwargs.get('primary_key', False) is True, "%ss must have primary_key=True." % self.__class__.__name__
@@ -478,7 +478,8 @@ def to_python(self, value):
try:
return int(value)
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):
pass
@@ -500,7 +501,7 @@ def formfield(self, **kwargs):
class BooleanField(Field):
empty_strings_allowed = False
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)")
def __init__(self, *args, **kwargs):
@@ -521,7 +522,8 @@ def to_python(self, value):
return True
if value in ('f', 'False', '0'):
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):
# Special-case handling for filters coming from a Web request (e.g. the
@@ -753,7 +755,7 @@ def formfield(self, **kwargs):
class DecimalField(Field):
empty_strings_allowed = False
default_error_messages = {
- 'invalid': _(u'This value must be a decimal number.'),
+ 'invalid': _(u"'%s' value must be a decimal number."),
}
description = _("Decimal number")
@@ -770,7 +772,8 @@ def to_python(self, value):
try:
return decimal.Decimal(value)
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):
if isinstance(value, basestring) or value is None:
@@ -848,7 +851,7 @@ def get_internal_type(self):
class FloatField(Field):
empty_strings_allowed = False
default_error_messages = {
- 'invalid': _("This value must be a float."),
+ 'invalid': _("'%s' value must be a float."),
}
description = _("Floating point number")
@@ -866,7 +869,8 @@ def to_python(self, value):
try:
return float(value)
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):
defaults = {'form_class': forms.FloatField}
@@ -876,7 +880,7 @@ def formfield(self, **kwargs):
class IntegerField(Field):
empty_strings_allowed = False
default_error_messages = {
- 'invalid': _("This value must be an integer."),
+ 'invalid': _("'%s' value must be an integer."),
}
description = _("Integer")
@@ -900,7 +904,8 @@ def to_python(self, value):
try:
return int(value)
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):
defaults = {'form_class': forms.IntegerField}
@@ -981,7 +986,7 @@ def formfield(self, **kwargs):
class NullBooleanField(Field):
empty_strings_allowed = False
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)")
@@ -1004,7 +1009,8 @@ def to_python(self, value):
return True
if value in ('f', 'False', '0'):
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):
# Special-case handling for filters coming from a Web request (e.g. the
57 tests/modeltests/validation/test_error_messages.py
View
@@ -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."])
Please sign in to comment.
Something went wrong with that request. Please try again.