Fixed #24531 -- Improved CommaSeparatedIntegerField validation.
`','`, `'1,,1'`, `',1'` etc. are no longer considered as valid comma-separated integer lists.
This commit is contained in:
parent
f4cc0c40a8
commit
3e64f3d0fc
|
@ -254,11 +254,14 @@ def ip_address_validators(protocol, unpack_ipv4):
|
||||||
raise ValueError("The protocol '%s' is unknown. Supported: %s"
|
raise ValueError("The protocol '%s' is unknown. Supported: %s"
|
||||||
% (protocol, list(ip_address_validator_map)))
|
% (protocol, list(ip_address_validator_map)))
|
||||||
|
|
||||||
comma_separated_int_list_re = re.compile('^[\d,]+$')
|
|
||||||
validate_comma_separated_integer_list = RegexValidator(
|
def int_list_validator(sep=',', message=None, code='invalid'):
|
||||||
comma_separated_int_list_re,
|
regexp = re.compile('^\d+(?:%s\d+)*$' % re.escape(sep))
|
||||||
_('Enter only digits separated by commas.'),
|
return RegexValidator(regexp, message=message, code=code)
|
||||||
'invalid'
|
|
||||||
|
|
||||||
|
validate_comma_separated_integer_list = int_list_validator(
|
||||||
|
message=_('Enter only digits separated by commas.'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,16 @@ to, or in lieu of custom ``field.clean()`` methods.
|
||||||
A :class:`RegexValidator` instance that ensures a value is a
|
A :class:`RegexValidator` instance that ensures a value is a
|
||||||
comma-separated list of integers.
|
comma-separated list of integers.
|
||||||
|
|
||||||
|
``int_list_validator``
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
.. function:: int_list_validator(sep=',', message=None, code='invalid')
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Returns a :class:`RegexValidator` instance that ensures a string
|
||||||
|
consists of integers separated by ``sep``.
|
||||||
|
|
||||||
``MaxValueValidator``
|
``MaxValueValidator``
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,8 @@ URLs
|
||||||
Validators
|
Validators
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
* ...
|
* Added :func:`django.core.validators.int_list_validator` to generate
|
||||||
|
validators of strings containing integers separated with a custom character.
|
||||||
|
|
||||||
Backwards incompatible changes in 1.9
|
Backwards incompatible changes in 1.9
|
||||||
=====================================
|
=====================================
|
||||||
|
@ -321,6 +322,9 @@ Miscellaneous
|
||||||
that value to construct absolute URLs have been moved to CSS for easier
|
that value to construct absolute URLs have been moved to CSS for easier
|
||||||
customization.
|
customization.
|
||||||
|
|
||||||
|
* ``CommaSeparatedIntegerField`` validation has been refined to forbid values
|
||||||
|
like ``','``, ``',1'``, and ``'1,,2'``.
|
||||||
|
|
||||||
.. _deprecated-features-1.9:
|
.. _deprecated-features-1.9:
|
||||||
|
|
||||||
Features deprecated in 1.9
|
Features deprecated in 1.9
|
||||||
|
|
|
@ -2136,24 +2136,28 @@ class ModelOtherFieldTests(TestCase):
|
||||||
model = CommaSeparatedInteger
|
model = CommaSeparatedInteger
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
f = CommaSeparatedIntegerForm({'field': '1'})
|
||||||
|
self.assertTrue(f.is_valid())
|
||||||
|
self.assertEqual(f.cleaned_data, {'field': '1'})
|
||||||
|
f = CommaSeparatedIntegerForm({'field': '12'})
|
||||||
|
self.assertTrue(f.is_valid())
|
||||||
|
self.assertEqual(f.cleaned_data, {'field': '12'})
|
||||||
f = CommaSeparatedIntegerForm({'field': '1,2,3'})
|
f = CommaSeparatedIntegerForm({'field': '1,2,3'})
|
||||||
self.assertTrue(f.is_valid())
|
self.assertTrue(f.is_valid())
|
||||||
self.assertEqual(f.cleaned_data, {'field': '1,2,3'})
|
self.assertEqual(f.cleaned_data, {'field': '1,2,3'})
|
||||||
|
f = CommaSeparatedIntegerForm({'field': '10,32'})
|
||||||
|
self.assertTrue(f.is_valid())
|
||||||
|
self.assertEqual(f.cleaned_data, {'field': '10,32'})
|
||||||
f = CommaSeparatedIntegerForm({'field': '1a,2'})
|
f = CommaSeparatedIntegerForm({'field': '1a,2'})
|
||||||
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
||||||
f = CommaSeparatedIntegerForm({'field': ',,,,'})
|
f = CommaSeparatedIntegerForm({'field': ',,,,'})
|
||||||
self.assertTrue(f.is_valid())
|
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
||||||
self.assertEqual(f.cleaned_data, {'field': ',,,,'})
|
|
||||||
f = CommaSeparatedIntegerForm({'field': '1.2'})
|
f = CommaSeparatedIntegerForm({'field': '1.2'})
|
||||||
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
||||||
f = CommaSeparatedIntegerForm({'field': '1,a,2'})
|
f = CommaSeparatedIntegerForm({'field': '1,a,2'})
|
||||||
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
||||||
f = CommaSeparatedIntegerForm({'field': '1,,2'})
|
f = CommaSeparatedIntegerForm({'field': '1,,2'})
|
||||||
self.assertTrue(f.is_valid())
|
self.assertEqual(f.errors, {'field': ['Enter only digits separated by commas.']})
|
||||||
self.assertEqual(f.cleaned_data, {'field': '1,,2'})
|
|
||||||
f = CommaSeparatedIntegerForm({'field': '1'})
|
|
||||||
self.assertTrue(f.is_valid())
|
|
||||||
self.assertEqual(f.cleaned_data, {'field': '1'})
|
|
||||||
|
|
||||||
def test_url_on_modelform(self):
|
def test_url_on_modelform(self):
|
||||||
"Check basic URL field validation on model forms"
|
"Check basic URL field validation on model forms"
|
||||||
|
|
|
@ -12,9 +12,9 @@ from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import (
|
from django.core.validators import (
|
||||||
BaseValidator, EmailValidator, MaxLengthValidator, MaxValueValidator,
|
BaseValidator, EmailValidator, MaxLengthValidator, MaxValueValidator,
|
||||||
MinLengthValidator, MinValueValidator, RegexValidator, URLValidator,
|
MinLengthValidator, MinValueValidator, RegexValidator, URLValidator,
|
||||||
validate_comma_separated_integer_list, validate_email, validate_integer,
|
int_list_validator, validate_comma_separated_integer_list, validate_email,
|
||||||
validate_ipv4_address, validate_ipv6_address, validate_ipv46_address,
|
validate_integer, validate_ipv4_address, validate_ipv6_address,
|
||||||
validate_slug,
|
validate_ipv46_address, validate_slug,
|
||||||
)
|
)
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
from django.test.utils import str_prefix
|
from django.test.utils import str_prefix
|
||||||
|
@ -120,12 +120,23 @@ TEST_DATA = [
|
||||||
(validate_ipv46_address, '12345::', ValidationError),
|
(validate_ipv46_address, '12345::', ValidationError),
|
||||||
|
|
||||||
(validate_comma_separated_integer_list, '1', None),
|
(validate_comma_separated_integer_list, '1', None),
|
||||||
|
(validate_comma_separated_integer_list, '12', None),
|
||||||
|
(validate_comma_separated_integer_list, '1,2', None),
|
||||||
(validate_comma_separated_integer_list, '1,2,3', None),
|
(validate_comma_separated_integer_list, '1,2,3', None),
|
||||||
(validate_comma_separated_integer_list, '1,2,3,', None),
|
(validate_comma_separated_integer_list, '10,32', None),
|
||||||
|
|
||||||
(validate_comma_separated_integer_list, '', ValidationError),
|
(validate_comma_separated_integer_list, '', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, 'a', ValidationError),
|
||||||
(validate_comma_separated_integer_list, 'a,b,c', ValidationError),
|
(validate_comma_separated_integer_list, 'a,b,c', ValidationError),
|
||||||
(validate_comma_separated_integer_list, '1, 2, 3', ValidationError),
|
(validate_comma_separated_integer_list, '1, 2, 3', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, ',', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, '1,2,3,', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, '1,2,', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, ',1', ValidationError),
|
||||||
|
(validate_comma_separated_integer_list, '1,,2', ValidationError),
|
||||||
|
|
||||||
|
(int_list_validator(sep='.'), '1.2.3', None),
|
||||||
|
(int_list_validator(sep='.'), '1,2,3', ValidationError),
|
||||||
|
|
||||||
(MaxValueValidator(10), 10, None),
|
(MaxValueValidator(10), 10, None),
|
||||||
(MaxValueValidator(10), -10, None),
|
(MaxValueValidator(10), -10, None),
|
||||||
|
|
Loading…
Reference in New Issue