Fixed #17051 -- Removed some 'invalid' field error messages
When the 'invalid' error message is set at field level, it masks the error message raised by the validator, if any.
This commit is contained in:
parent
34d098665d
commit
2f121dfe63
|
@ -7,7 +7,7 @@ from django.contrib.auth.forms import (UserCreationForm, AuthenticationForm,
|
||||||
ReadOnlyPasswordHashField, ReadOnlyPasswordHashWidget)
|
ReadOnlyPasswordHashField, ReadOnlyPasswordHashWidget)
|
||||||
from django.contrib.auth.tests.utils import skipIfCustomUser
|
from django.contrib.auth.tests.utils import skipIfCustomUser
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.forms.fields import Field, EmailField, CharField
|
from django.forms.fields import Field, CharField
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
@ -322,8 +322,7 @@ class PasswordResetFormTest(TestCase):
|
||||||
data = {'email': 'not valid'}
|
data = {'email': 'not valid'}
|
||||||
form = PasswordResetForm(data)
|
form = PasswordResetForm(data)
|
||||||
self.assertFalse(form.is_valid())
|
self.assertFalse(form.is_valid())
|
||||||
self.assertEqual(form['email'].errors,
|
self.assertEqual(form['email'].errors, [_('Enter a valid email address.')])
|
||||||
[force_text(EmailField.default_error_messages['invalid'])])
|
|
||||||
|
|
||||||
def test_nonexistant_email(self):
|
def test_nonexistant_email(self):
|
||||||
# Test nonexistant email address. This should not fail because it would
|
# Test nonexistant email address. This should not fail because it would
|
||||||
|
|
|
@ -80,7 +80,7 @@ def validate_integer(value):
|
||||||
|
|
||||||
|
|
||||||
class EmailValidator(object):
|
class EmailValidator(object):
|
||||||
message = _('Enter a valid e-mail address.')
|
message = _('Enter a valid email address.')
|
||||||
code = 'invalid'
|
code = 'invalid'
|
||||||
user_regex = re.compile(
|
user_regex = re.compile(
|
||||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$" # dot-atom
|
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*$" # dot-atom
|
||||||
|
|
|
@ -49,9 +49,10 @@ class Field(object):
|
||||||
widget = TextInput # Default widget to use when rendering this type of Field.
|
widget = TextInput # Default widget to use when rendering this type of Field.
|
||||||
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
|
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
|
||||||
default_validators = [] # Default set of validators
|
default_validators = [] # Default set of validators
|
||||||
|
# Add an 'invalid' entry to default_error_message if you want a specific
|
||||||
|
# field error message not raised by the field validators.
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'required': _('This field is required.'),
|
'required': _('This field is required.'),
|
||||||
'invalid': _('Enter a valid value.'),
|
|
||||||
}
|
}
|
||||||
empty_values = list(validators.EMPTY_VALUES)
|
empty_values = list(validators.EMPTY_VALUES)
|
||||||
|
|
||||||
|
@ -225,8 +226,6 @@ class CharField(Field):
|
||||||
class IntegerField(Field):
|
class IntegerField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('Enter a whole number.'),
|
'invalid': _('Enter a whole number.'),
|
||||||
'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'),
|
|
||||||
'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, max_value=None, min_value=None, *args, **kwargs):
|
def __init__(self, max_value=None, min_value=None, *args, **kwargs):
|
||||||
|
@ -504,9 +503,6 @@ class RegexField(CharField):
|
||||||
|
|
||||||
class EmailField(CharField):
|
class EmailField(CharField):
|
||||||
widget = EmailInput
|
widget = EmailInput
|
||||||
default_error_messages = {
|
|
||||||
'invalid': _('Enter a valid email address.'),
|
|
||||||
}
|
|
||||||
default_validators = [validators.validate_email]
|
default_validators = [validators.validate_email]
|
||||||
|
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
|
@ -1082,9 +1078,6 @@ class SplitDateTimeField(MultiValueField):
|
||||||
|
|
||||||
|
|
||||||
class IPAddressField(CharField):
|
class IPAddressField(CharField):
|
||||||
default_error_messages = {
|
|
||||||
'invalid': _('Enter a valid IPv4 address.'),
|
|
||||||
}
|
|
||||||
default_validators = [validators.validate_ipv4_address]
|
default_validators = [validators.validate_ipv4_address]
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
|
@ -1094,13 +1087,9 @@ class IPAddressField(CharField):
|
||||||
|
|
||||||
|
|
||||||
class GenericIPAddressField(CharField):
|
class GenericIPAddressField(CharField):
|
||||||
default_error_messages = {}
|
|
||||||
|
|
||||||
def __init__(self, protocol='both', unpack_ipv4=False, *args, **kwargs):
|
def __init__(self, protocol='both', unpack_ipv4=False, *args, **kwargs):
|
||||||
self.unpack_ipv4 = unpack_ipv4
|
self.unpack_ipv4 = unpack_ipv4
|
||||||
self.default_validators, invalid_error_message = \
|
self.default_validators = validators.ip_address_validators(protocol, unpack_ipv4)[0]
|
||||||
validators.ip_address_validators(protocol, unpack_ipv4)
|
|
||||||
self.default_error_messages['invalid'] = invalid_error_message
|
|
||||||
super(GenericIPAddressField, self).__init__(*args, **kwargs)
|
super(GenericIPAddressField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
|
@ -1108,14 +1097,9 @@ class GenericIPAddressField(CharField):
|
||||||
return ''
|
return ''
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
if value and ':' in value:
|
if value and ':' in value:
|
||||||
return clean_ipv6_address(value,
|
return clean_ipv6_address(value, self.unpack_ipv4)
|
||||||
self.unpack_ipv4, self.error_messages['invalid'])
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class SlugField(CharField):
|
class SlugField(CharField):
|
||||||
default_error_messages = {
|
|
||||||
'invalid': _("Enter a valid 'slug' consisting of letters, numbers,"
|
|
||||||
" underscores or hyphens."),
|
|
||||||
}
|
|
||||||
default_validators = [validators.validate_slug]
|
default_validators = [validators.validate_slug]
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError
|
||||||
from django.utils.six.moves import xrange
|
from django.utils.six.moves import xrange
|
||||||
|
|
||||||
def clean_ipv6_address(ip_str, unpack_ipv4=False,
|
def clean_ipv6_address(ip_str, unpack_ipv4=False,
|
||||||
error_message="This is not a valid IPv6 address"):
|
error_message="This is not a valid IPv6 address."):
|
||||||
"""
|
"""
|
||||||
Cleans a IPv6 address string.
|
Cleans a IPv6 address string.
|
||||||
|
|
||||||
|
|
|
@ -181,24 +181,20 @@ the field's ``validators`` argument, or defined on the Field class itself with
|
||||||
the ``default_validators`` attribute.
|
the ``default_validators`` attribute.
|
||||||
|
|
||||||
Simple validators can be used to validate values inside the field, let's have
|
Simple validators can be used to validate values inside the field, let's have
|
||||||
a look at Django's ``EmailField``::
|
a look at Django's ``SlugField``::
|
||||||
|
|
||||||
class EmailField(CharField):
|
class SlugField(CharField):
|
||||||
default_error_messages = {
|
default_validators = [validators.validate_slug]
|
||||||
'invalid': _('Enter a valid email address.'),
|
|
||||||
}
|
|
||||||
default_validators = [validators.validate_email]
|
|
||||||
|
|
||||||
As you can see, ``EmailField`` is just a ``CharField`` with customized error
|
As you can see, ``SlugField`` is just a ``CharField`` with a customized
|
||||||
message and a validator that validates email addresses. This can also be done
|
validator that validates that submitted text obeys to some character rules.
|
||||||
on field definition so::
|
This can also be done on field definition so::
|
||||||
|
|
||||||
email = forms.EmailField()
|
slug = forms.SlugField()
|
||||||
|
|
||||||
is equivalent to::
|
is equivalent to::
|
||||||
|
|
||||||
email = forms.CharField(validators=[validators.validate_email],
|
slug = forms.CharField(validators=[validators.validate_slug])
|
||||||
error_messages={'invalid': _('Enter a valid email address.')})
|
|
||||||
|
|
||||||
|
|
||||||
Form field default cleaning
|
Form field default cleaning
|
||||||
|
|
|
@ -506,11 +506,11 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '256.125.1.5')
|
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '256.125.1.5')
|
||||||
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
||||||
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '12345:2:3:4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '12345:2:3:4')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1::2:3::4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3::4')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1:2')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1:2')
|
||||||
|
|
||||||
def test_generic_ipaddress_as_ipv4_only(self):
|
def test_generic_ipaddress_as_ipv4_only(self):
|
||||||
f = GenericIPAddressField(protocol="IPv4")
|
f = GenericIPAddressField(protocol="IPv4")
|
||||||
|
@ -535,11 +535,11 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '256.125.1.5')
|
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '256.125.1.5')
|
||||||
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
||||||
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '12345:2:3:4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '12345:2:3:4')
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '1::2:3::4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3::4')
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
||||||
self.assertFormErrors(['Enter a valid IPv6 address.'], f.clean, '1:2')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1:2')
|
||||||
|
|
||||||
def test_generic_ipaddress_as_generic_not_required(self):
|
def test_generic_ipaddress_as_generic_not_required(self):
|
||||||
f = GenericIPAddressField(required=False)
|
f = GenericIPAddressField(required=False)
|
||||||
|
@ -552,11 +552,11 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '256.125.1.5')
|
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '256.125.1.5')
|
||||||
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' fe80::223:6cff:fe8a:2e8a '), 'fe80::223:6cff:fe8a:2e8a')
|
||||||
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
self.assertEqual(f.clean(' 2a02::223:6cff:fe8a:2e8a '), '2a02::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '12345:2:3:4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '12345:2:3:4')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1::2:3::4')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3::4')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, 'foo::223:6cff:fe8a:2e8a')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1::2:3:4:5:6:7:8')
|
||||||
self.assertFormErrors(['Enter a valid IPv4 or IPv6 address.'], f.clean, '1:2')
|
self.assertFormErrors(['This is not a valid IPv6 address.'], f.clean, '1:2')
|
||||||
|
|
||||||
def test_generic_ipaddress_normalization(self):
|
def test_generic_ipaddress_normalization(self):
|
||||||
# Test the normalising code
|
# Test the normalising code
|
||||||
|
|
|
@ -1,16 +1,39 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.unittest import TestCase
|
from django.utils.unittest import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class UserForm(forms.Form):
|
||||||
|
full_name = forms.CharField(
|
||||||
|
max_length = 50,
|
||||||
|
validators = [
|
||||||
|
validators.validate_integer,
|
||||||
|
validators.validate_email,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
string = forms.CharField(
|
||||||
|
max_length = 50,
|
||||||
|
validators = [
|
||||||
|
validators.RegexValidator(
|
||||||
|
regex='^[a-zA-Z]*$',
|
||||||
|
message="Letters only.",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestFieldWithValidators(TestCase):
|
class TestFieldWithValidators(TestCase):
|
||||||
def test_all_errors_get_reported(self):
|
def test_all_errors_get_reported(self):
|
||||||
field = forms.CharField(
|
form = UserForm({'full_name': 'not int nor mail', 'string': '2 is not correct'})
|
||||||
validators=[validators.validate_integer, validators.validate_email]
|
self.assertRaises(ValidationError, form.fields['full_name'].clean, 'not int nor mail')
|
||||||
)
|
|
||||||
self.assertRaises(ValidationError, field.clean, 'not int nor mail')
|
|
||||||
try:
|
try:
|
||||||
field.clean('not int nor mail')
|
form.fields['full_name'].clean('not int nor mail')
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
self.assertEqual(2, len(e.messages))
|
self.assertEqual(2, len(e.messages))
|
||||||
|
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(form.errors['string'], ["Letters only."])
|
||||||
|
|
Loading…
Reference in New Issue