Fixed #22206 -- Passed models.TextField.max_length to forms.CharField.maxlength
This commit is contained in:
parent
ac699cdc17
commit
95c74b9d69
1
AUTHORS
1
AUTHORS
|
@ -666,6 +666,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Rachel Willmer <http://www.willmer.com/kb/>
|
Rachel Willmer <http://www.willmer.com/kb/>
|
||||||
Jakub Wilk <ubanus@users.sf.net>
|
Jakub Wilk <ubanus@users.sf.net>
|
||||||
Ian A Wilson <http://ianawilson.com>
|
Ian A Wilson <http://ianawilson.com>
|
||||||
|
Chris Wilson <chris+github@qwirx.com>
|
||||||
Jakub Wiśniowski <restless.being@gmail.com>
|
Jakub Wiśniowski <restless.being@gmail.com>
|
||||||
Maciej Wiśniowski <pigletto@gmail.com>
|
Maciej Wiśniowski <pigletto@gmail.com>
|
||||||
wojtek
|
wojtek
|
||||||
|
|
|
@ -1850,7 +1850,10 @@ class TextField(Field):
|
||||||
return smart_text(value)
|
return smart_text(value)
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
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)
|
defaults.update(kwargs)
|
||||||
return super(TextField, self).formfield(**defaults)
|
return super(TextField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ class CharField(Field):
|
||||||
|
|
||||||
def widget_attrs(self, widget):
|
def widget_attrs(self, widget):
|
||||||
attrs = super(CharField, self).widget_attrs(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.
|
# The HTML attribute is maxlength, not max_length.
|
||||||
attrs.update({'maxlength': str(self.max_length)})
|
attrs.update({'maxlength': str(self.max_length)})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
|
@ -968,6 +968,13 @@ databases supported by Django.
|
||||||
A large text field. The default form widget for this field is a
|
A large text field. The default form widget for this field is a
|
||||||
:class:`~django.forms.Textarea`.
|
: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
|
.. admonition:: MySQL users
|
||||||
|
|
||||||
If you are using this field with MySQLdb 1.2.1p2 and the ``utf8_bin``
|
If you are using this field with MySQLdb 1.2.1p2 and the ``utf8_bin``
|
||||||
|
|
|
@ -488,6 +488,10 @@ Forms
|
||||||
Each radio button or checkbox includes an ``id_for_label`` attribute to
|
Each radio button or checkbox includes an ``id_for_label`` attribute to
|
||||||
output the element's ID.
|
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
|
* :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
|
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
|
or ``None`` for the key and the custom label as the value. The default blank
|
||||||
|
|
|
@ -38,7 +38,7 @@ from django.forms import (
|
||||||
DecimalField, EmailField, Field, FileField, FilePathField, FloatField,
|
DecimalField, EmailField, Field, FileField, FilePathField, FloatField,
|
||||||
Form, forms, HiddenInput, IntegerField, MultipleChoiceField,
|
Form, forms, HiddenInput, IntegerField, MultipleChoiceField,
|
||||||
NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField,
|
NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField,
|
||||||
SplitDateTimeField, TextInput, TimeField, TypedChoiceField,
|
SplitDateTimeField, TextInput, Textarea, TimeField, TypedChoiceField,
|
||||||
TypedMultipleChoiceField, URLField, ValidationError, Widget,
|
TypedMultipleChoiceField, URLField, ValidationError, Widget,
|
||||||
)
|
)
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
|
@ -148,14 +148,13 @@ class FieldsTests(SimpleTestCase):
|
||||||
# Return an empty dictionary if max_length is None
|
# Return an empty dictionary if max_length is None
|
||||||
f = CharField()
|
f = CharField()
|
||||||
self.assertEqual(f.widget_attrs(TextInput()), {})
|
self.assertEqual(f.widget_attrs(TextInput()), {})
|
||||||
|
self.assertEqual(f.widget_attrs(Textarea()), {})
|
||||||
# Or if the widget is not TextInput or PasswordInput
|
|
||||||
f = CharField(max_length=10)
|
|
||||||
self.assertEqual(f.widget_attrs(HiddenInput()), {})
|
|
||||||
|
|
||||||
# Otherwise, return a maxlength attribute equal to max_length
|
# 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(TextInput()), {'maxlength': '10'})
|
||||||
self.assertEqual(f.widget_attrs(PasswordInput()), {'maxlength': '10'})
|
self.assertEqual(f.widget_attrs(PasswordInput()), {'maxlength': '10'})
|
||||||
|
self.assertEqual(f.widget_attrs(Textarea()), {'maxlength': '10'})
|
||||||
|
|
||||||
# IntegerField ################################################################
|
# IntegerField ################################################################
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,21 @@ class BooleanFieldTests(unittest.TestCase):
|
||||||
def test_nullbooleanfield_to_python(self):
|
def test_nullbooleanfield_to_python(self):
|
||||||
self._test_to_python(models.NullBooleanField())
|
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):
|
def test_booleanfield_choices_blank(self):
|
||||||
"""
|
"""
|
||||||
Test that BooleanField with choices and defaults doesn't generate a
|
Test that BooleanField with choices and defaults doesn't generate a
|
||||||
|
|
|
@ -533,7 +533,7 @@ class TestFieldOverridesByFormMeta(TestCase):
|
||||||
form = FieldOverridesByFormMetaForm()
|
form = FieldOverridesByFormMetaForm()
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
str(form['name']),
|
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(
|
self.assertHTMLEqual(
|
||||||
str(form['url']),
|
str(form['url']),
|
||||||
|
|
Loading…
Reference in New Issue