diff options
| author | Chris Wilson <chris+github@qwirx.com> | 2014-03-04 14:12:13 +0000 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2014-03-05 20:09:28 +0100 |
| commit | 95c74b9d699c29fe808684774548e2864d64665a (patch) | |
| tree | 8edba19c8beba0a514b65f2f28a2c8c02e47b91f | |
| parent | ac699cdc174a825e6b78c6f3c6e967bc961413c8 (diff) | |
Fixed #22206 -- Passed models.TextField.max_length to forms.CharField.maxlength
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/db/models/fields/__init__.py | 5 | ||||
| -rw-r--r-- | django/forms/fields.py | 2 | ||||
| -rw-r--r-- | docs/ref/models/fields.txt | 7 | ||||
| -rw-r--r-- | docs/releases/1.7.txt | 4 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_fields.py | 9 | ||||
| -rw-r--r-- | tests/model_fields/tests.py | 15 | ||||
| -rw-r--r-- | tests/model_forms/tests.py | 2 |
8 files changed, 37 insertions, 8 deletions
@@ -666,6 +666,7 @@ answer newbie questions, and generally made Django that much better: Rachel Willmer <http://www.willmer.com/kb/> Jakub Wilk <ubanus@users.sf.net> Ian A Wilson <http://ianawilson.com> + Chris Wilson <chris+github@qwirx.com> Jakub Wiśniowski <restless.being@gmail.com> Maciej Wiśniowski <pigletto@gmail.com> wojtek diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 25ac74caee..5e94e78c58 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -1850,7 +1850,10 @@ class TextField(Field): return smart_text(value) def formfield(self, **kwargs): - defaults = {'widget': forms.Textarea} + # Passing 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, 'widget': forms.Textarea} defaults.update(kwargs) return super(TextField, self).formfield(**defaults) diff --git a/django/forms/fields.py b/django/forms/fields.py index 8b5fd2c55e..1866bc1786 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -223,7 +223,7 @@ class CharField(Field): def widget_attrs(self, widget): attrs = super(CharField, self).widget_attrs(widget) - if self.max_length is not None and isinstance(widget, TextInput): + if self.max_length is not None: # The HTML attribute is maxlength, not max_length. attrs.update({'maxlength': str(self.max_length)}) return attrs diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 4e02c66ca0..b3523334c0 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -968,6 +968,13 @@ databases supported by Django. A large text field. The default form widget for this field is a :class:`~django.forms.Textarea`. +.. versionchanged:: 1.7 + + If you specify a ``max_length`` attribute, it will be reflected in the + :class:`~django.forms.Textarea` widget of the auto-generated form field. + However it is not enforced at the model or database level. Use a + :class:`CharField` for that. + .. admonition:: MySQL users If you are using this field with MySQLdb 1.2.1p2 and the ``utf8_bin`` diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 441a39616a..096415c5b8 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -488,6 +488,10 @@ Forms Each radio button or checkbox includes an ``id_for_label`` attribute to output the element's ID. +* The ``<textarea>`` tags rendered by :class:`~django.forms.Textarea` now + include a ``maxlength`` attribute if the :class:`~django.db.models.TextField` + model field has a ``max_length``. + * :attr:`Field.choices<django.db.models.Field.choices>` now allows you to customize the "empty choice" label by including a tuple with an empty string or ``None`` for the key and the custom label as the value. The default blank diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index 8cea26c37c..5a42e4b95d 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -38,7 +38,7 @@ from django.forms import ( DecimalField, EmailField, Field, FileField, FilePathField, FloatField, Form, forms, HiddenInput, IntegerField, MultipleChoiceField, NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField, - SplitDateTimeField, TextInput, TimeField, TypedChoiceField, + SplitDateTimeField, TextInput, Textarea, TimeField, TypedChoiceField, TypedMultipleChoiceField, URLField, ValidationError, Widget, ) from django.test import SimpleTestCase @@ -148,14 +148,13 @@ class FieldsTests(SimpleTestCase): # Return an empty dictionary if max_length is None f = CharField() self.assertEqual(f.widget_attrs(TextInput()), {}) - - # Or if the widget is not TextInput or PasswordInput - f = CharField(max_length=10) - self.assertEqual(f.widget_attrs(HiddenInput()), {}) + self.assertEqual(f.widget_attrs(Textarea()), {}) # Otherwise, return a maxlength attribute equal to max_length + f = CharField(max_length=10) self.assertEqual(f.widget_attrs(TextInput()), {'maxlength': '10'}) self.assertEqual(f.widget_attrs(PasswordInput()), {'maxlength': '10'}) + self.assertEqual(f.widget_attrs(Textarea()), {'maxlength': '10'}) # IntegerField ################################################################ diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index f9d1a76078..194219a114 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -203,6 +203,21 @@ class BooleanFieldTests(unittest.TestCase): def test_nullbooleanfield_to_python(self): self._test_to_python(models.NullBooleanField()) + def test_charfield_textfield_max_length_passed_to_formfield(self): + """ + Test that CharField and TextField pass their max_length attributes to + form fields created using their .formfield() method (#22206). + """ + cf1 = models.CharField() + cf2 = models.CharField(max_length=1234) + self.assertIsNone(cf1.formfield().max_length) + self.assertEqual(1234, cf2.formfield().max_length) + + tf1 = models.TextField() + tf2 = models.TextField(max_length=2345) + self.assertIsNone(tf1.formfield().max_length) + self.assertEqual(2345, tf2.formfield().max_length) + def test_booleanfield_choices_blank(self): """ Test that BooleanField with choices and defaults doesn't generate a diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index ba72db6bdc..c75921c6e3 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -533,7 +533,7 @@ class TestFieldOverridesByFormMeta(TestCase): form = FieldOverridesByFormMetaForm() self.assertHTMLEqual( str(form['name']), - '<textarea id="id_name" rows="10" cols="40" name="name"></textarea>', + '<textarea id="id_name" rows="10" cols="40" name="name" maxlength="20"></textarea>', ) self.assertHTMLEqual( str(form['url']), |
