Skip to content

Loading…

Fixes #20440 - forms.CharField should return an exception if max_length is not an integer #1109

Closed
wants to merge 6 commits into from

2 participants

@cvitan

In models.CharField you can define a verbose_name by placing a string as the first parameter, i.e. models.CharField("foo")
If you by mistake happen to define a forms.CharField with the same pattern, i.e. forms.CharField("foo"), there will be no error message and the input field will be rendered with the attribute maxlength="foo" which is invalid.

The proposed solution is to attempt to cast non-empty max_length and min_length values to an int in the init method of CharField.

@claudep
Django member

Thanks, pushed in caf56ad. I've reworked the patch a bit, hopefully you won't mind.

@claudep claudep closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 18, 2013
  1. @cvitan

    Added casting to int of max_length and min_length in order to make su…

    cvitan committed
    …re that they contain an integer.
  2. @cvitan

    PEP-8

    cvitan committed
  3. @cvitan

    Added myself to the authors file

    cvitan committed
  4. @cvitan

    Improved test description

    cvitan committed
  5. @cvitan
  6. @cvitan
Showing with 27 additions and 0 deletions.
  1. +1 −0 AUTHORS
  2. +12 −0 django/forms/fields.py
  3. +14 −0 tests/forms_tests/tests/test_fields.py
View
1 AUTHORS
@@ -162,6 +162,7 @@ answer newbie questions, and generally made Django that much better:
Leah Culver <leah.culver@gmail.com>
Raúl Cumplido <raulcumplido@gmail.com>
flavio.curella@gmail.com
+ Tome Cvitan <tome@cvitan.com>
John D'Agostino <john.dagostino@gmail.com>
dackze+django@gmail.com
Jim Dalton <jim.dalton@gmail.com>
View
12 django/forms/fields.py
@@ -198,13 +198,16 @@ def __deepcopy__(self, memo):
result.validators = self.validators[:]
return result
+
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)
if min_length is not None:
+ min_length = int(min_length)
self.validators.append(validators.MinLengthValidator(min_length))
if max_length is not None:
+ max_length = int(max_length)
self.validators.append(validators.MaxLengthValidator(max_length))
def to_python(self, value):
@@ -220,6 +223,7 @@ def widget_attrs(self, widget):
attrs.update({'maxlength': str(self.max_length)})
return attrs
+
class IntegerField(Field):
default_error_messages = {
'invalid': _('Enter a whole number.'),
@@ -444,6 +448,7 @@ def to_python(self, value):
def strptime(self, value, format):
return datetime.datetime.strptime(force_str(value), format).time()
+
class DateTimeField(BaseTemporalField):
widget = DateTimeInput
input_formats = formats.get_format_lazy('DATETIME_INPUT_FORMATS')
@@ -482,6 +487,7 @@ def to_python(self, value):
def strptime(self, value, format):
return datetime.datetime.strptime(force_str(value), format)
+
class RegexField(CharField):
def __init__(self, regex, max_length=None, min_length=None, error_message=None, *args, **kwargs):
"""
@@ -511,6 +517,7 @@ def _set_regex(self, regex):
regex = property(_get_regex, _set_regex)
+
class EmailField(CharField):
widget = EmailInput
default_validators = [validators.validate_email]
@@ -519,6 +526,7 @@ def clean(self, value):
value = self.to_python(value).strip()
return super(EmailField, self).clean(value)
+
class FileField(Field):
widget = ClearableFileInput
default_error_messages = {
@@ -626,6 +634,7 @@ def to_python(self, data):
f.seek(0)
return f
+
class URLField(CharField):
widget = URLInput
default_error_messages = {
@@ -788,6 +797,7 @@ def valid_value(self, value):
return True
return False
+
class TypedChoiceField(ChoiceField):
def __init__(self, *args, **kwargs):
self.coerce = kwargs.pop('coerce', lambda val: val)
@@ -899,6 +909,7 @@ def clean(self, value):
value = field.clean(value)
return value
+
class MultiValueField(Field):
"""
A Field that aggregates the logic of multiple Fields.
@@ -1043,6 +1054,7 @@ def __init__(self, path, match=None, recursive=False, allow_files=True,
self.widget.choices = self.choices
+
class SplitDateTimeField(MultiValueField):
widget = SplitDateTimeWidget
hidden_widget = SplitHiddenDateTimeWidget
View
14 tests/forms_tests/tests/test_fields.py
@@ -125,6 +125,20 @@ def test_charfield_5(self):
self.assertEqual(f.max_length, None)
self.assertEqual(f.min_length, 10)
+ def test_charfield_min_length_not_int(self):
+ """
+ Ensure that setting min_length to something that is not a number returns an exception.
+ Refs #20440
+ """
+ self.assertRaises(ValueError, CharField, min_length='a')
+
+ def test_charfield_max_length_not_int(self):
+ """
+ Ensure that setting max_length to something that is not a number returns an exception.
+ Refs #20440
+ """
+ self.assertRaises(ValueError, CharField, max_length='a')
+
def test_charfield_widget_attrs(self):
"""
Ensure that CharField.widget_attrs() always returns a dictionary.
Something went wrong with that request. Please try again.