From ff0eff055ea7cd28ba2856b89189d03dbe71c397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Honza=20Kr=C3=A1l?= Date: Sun, 5 Jul 2009 13:30:17 +0000 Subject: [PATCH] [soc2009/model-validation] Added min and max length validator. CharField now validates it's value's length using a validator. git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/model-validation@11194 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/validators.py | 28 ++++++++++++++++++++++++++++ django/db/models/fields/__init__.py | 7 +++++++ django/forms/fields.py | 5 +++++ tests/modeltests/validation/tests.py | 4 ++++ 4 files changed, 44 insertions(+) diff --git a/django/core/validators.py b/django/core/validators.py index 6758a387b0..3fc750481e 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -40,6 +40,7 @@ def validate_ipv4_address(value): code="invalid" ) + class MaxValueValidator(object): def __init__(self, max_value): self.max_value = max_value @@ -51,6 +52,7 @@ class MaxValueValidator(object): code='max_value', params=(self.max_value,) ) + class MinValueValidator(object): def __init__(self, min_value): self.min_value = min_value @@ -63,6 +65,32 @@ class MinValueValidator(object): params=(self.min_value,) ) +class MinLengthValidator(object): + def __init__(self, min_length): + self.min_length = min_length + + def __call__(self, value): + value_len = len(value) + if value_len < self.min_length: + raise ValidationError( + _(u'Ensure this value has at least %(min)d characters (it has %(length)d).'), + code='min_length', + params={ 'min': self.min_length, 'length': value_len} + ) + +class MaxLengthValidator(object): + def __init__(self, max_length): + self.max_length = max_length + + def __call__(self, value): + value_len = len(value) + if value_len > self.max_length: + raise ValidationError( + _(u'Ensure this value has at most %(max)d characters (it has %(length)d).'), + code='max_length', + params={ 'max': self.max_length, 'length': value_len} + ) + class ComplexValidator(object): def get_value(self, name, all_values, obj): assert all_values or obj, "Either all_values or obj must be supplied" diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index f60ef4cc25..8b51ac69a9 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -469,6 +469,10 @@ class BooleanField(Field): return super(BooleanField, self).formfield(**defaults) class CharField(Field): + def __init__(self, *args, **kwargs): + super(CharField, self).__init__(*args, **kwargs) + self.validators.append(validators.MaxLengthValidator(self.max_length)) + def get_internal_type(self): return "CharField" @@ -478,6 +482,9 @@ class CharField(Field): return smart_unicode(value) def formfield(self, **kwargs): + # passing of max_length to forms.CharField means that the value's length + # will be validated twice. This is considered acceptable since we want + # the value in the form field (to pass into widget for example). defaults = {'max_length': self.max_length} defaults.update(kwargs) return super(CharField, self).formfield(**defaults) diff --git a/django/forms/fields.py b/django/forms/fields.py index 02e80456ab..b21b936004 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -172,6 +172,11 @@ class CharField(Field): def __init__(self, max_length=None, min_length=None, *args, **kwargs): self.max_length, self.min_length = max_length, min_length super(CharField, self).__init__(*args, **kwargs) + # TODO: use this as soon as you make regex validator and use it in RegexField + #if min_length is not None: + # self.validators.append(validators.MinLengthValidator(min_length)) + #if max_length is not None: + # self.validators.append(validators.MaxLengthValidator(max_length)) def to_python(self, value): "Returns a Unicode object." diff --git a/tests/modeltests/validation/tests.py b/tests/modeltests/validation/tests.py index 95952a5a24..e6d1697ce2 100644 --- a/tests/modeltests/validation/tests.py +++ b/tests/modeltests/validation/tests.py @@ -39,6 +39,10 @@ class BaseModelValidationTests(ValidationTestCase): mtv = ModelToValidate(number=10, name='Some Name', email='valid@email.com') self.assertEqual(None, mtv.clean()) + def test_text_greater_that_charfields_max_length_eaises_erros(self): + mtv = ModelToValidate(number=10, name='Some Name'*100) + self.assertFailsValidation(mtv.clean, ['name',]) + class GetUniqueCheckTests(unittest.TestCase): def test_unique_fields_get_collected(self): m = UniqueFieldsModel()