diff options
| author | Gabe Jackson <gabejackson@cxg.ch> | 2012-06-08 15:32:35 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-06-10 14:23:15 -0400 |
| commit | 584bd14dcfdee9585fec7794d53ce120ea73d0bc (patch) | |
| tree | 7303b054d610767073934793ae1223404444c9de | |
| parent | a643e4d200e12d1570174fec343a27d6bc47f735 (diff) | |
Fixed #18134 -- BoundField.label_tag now includes the form's label_suffix
There was an inconsistency between how the label_tag for forms were
generated depending on which method was used: as_p, as_ul and as_table
contained code to append the label_suffix where as label_tag called on a
form field directly did NOT append the label_suffix. The code for
appending the label_suffix has been moved in to the label_tag code of
the field and the HTML generation code for as_p, as_ul and as_table now
calls this code as well.
This is a backwards incompatible change because users who have added the
label_suffix manually in their templates may now get double label_suffix
characters in their forms.
| -rw-r--r-- | django/forms/forms.py | 9 | ||||
| -rw-r--r-- | docs/ref/forms/api.txt | 9 | ||||
| -rw-r--r-- | docs/releases/1.6.txt | 31 | ||||
| -rw-r--r-- | docs/topics/forms/index.txt | 16 | ||||
| -rw-r--r-- | docs/topics/forms/modelforms.txt | 2 | ||||
| -rw-r--r-- | tests/admin_util/tests.py | 4 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_forms.py | 36 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_regressions.py | 4 |
8 files changed, 77 insertions, 34 deletions
diff --git a/django/forms/forms.py b/django/forms/forms.py index 0c598ac775..e6a11f28fb 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -170,11 +170,6 @@ class BaseForm(object): if bf.label: label = conditional_escape(force_text(bf.label)) - # Only add the suffix if the label does not end in - # punctuation. - if self.label_suffix: - if label[-1] not in ':?.!': - label = format_html('{0}{1}', label, self.label_suffix) label = bf.label_tag(label) or '' else: label = '' @@ -522,6 +517,10 @@ class BoundField(object): If attrs are given, they're used as HTML attributes on the <label> tag. """ contents = contents or self.label + # Only add the suffix if the label does not end in punctuation. + if self.form.label_suffix: + if contents[-1] not in ':?.!': + contents = format_html('{0}{1}', contents, self.form.label_suffix) widget = self.field.widget id_ = widget.attrs.get('id') or self.auto_id if id_: diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt index c05430c64e..3c17827800 100644 --- a/docs/ref/forms/api.txt +++ b/docs/ref/forms/api.txt @@ -498,6 +498,8 @@ include ``%s`` -- then the library will act as if ``auto_id`` is ``True``. By default, ``auto_id`` is set to the string ``'id_%s'``. +.. attribute:: Form.label_suffix + Normally, a colon (``:``) will be appended after any label name when a form is rendered. It's possible to change the colon to another character, or omit it entirely, using the ``label_suffix`` parameter:: @@ -650,12 +652,17 @@ To separately render the label tag of a form field, you can call its >>> f = ContactForm(data) >>> print(f['message'].label_tag()) - <label for="id_message">Message</label> + <label for="id_message">Message:</label> Optionally, you can provide the ``contents`` parameter which will replace the auto-generated label tag. An optional ``attrs`` dictionary may contain additional attributes for the ``<label>`` tag. +.. versionchanged:: 1.6 + + The label now includes the form's :attr:`~django.forms.Form.label_suffix` + (a semicolon, by default). + .. method:: BoundField.css_classes() When you use Django's rendering shortcuts, CSS classes are used to diff --git a/docs/releases/1.6.txt b/docs/releases/1.6.txt index 6736af8c2d..e5cd3273dc 100644 --- a/docs/releases/1.6.txt +++ b/docs/releases/1.6.txt @@ -581,6 +581,37 @@ It is still possible to convert the fetched rows to ``Model`` objects lazily by using the :meth:`~django.db.models.query.QuerySet.iterator()` method. +:meth:`BoundField.label_tag<django.forms.BoundField.label_tag>` now includes the form's :attr:`~django.forms.Form.label_suffix` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is consistent with how methods like +:meth:`Form.as_p<django.forms.Form.as_p>` and +:meth:`Form.as_ul<django.forms.Form.as_ul>` render labels. + +If you manually render ``label_tag`` in your templates: + +.. code-block:: html+django + + {{ form.my_field.label_tag }}: {{ form.my_field }} + +you'll want to remove the semicolon (or whatever other separator you may be +using) to avoid duplicating it when upgrading to Django 1.6. The following +template in Django 1.6 will render identically to the above template in Django +1.5, except that the semicolon will appear inside the ``<label>`` element. + +.. code-block:: html+django + + {{ form.my_field.label_tag }} {{ form.my_field }} + +will render something like: + +.. code-block:: html + + <label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" /> + +If you want to keep the current behavior of rendering ``label_tag`` without +the ``label_suffix``, instantiate the form ``label_suffix=''``. + Miscellaneous ~~~~~~~~~~~~~ diff --git a/docs/topics/forms/index.txt b/docs/topics/forms/index.txt index ac58acc9e3..7d5a0ed411 100644 --- a/docs/topics/forms/index.txt +++ b/docs/topics/forms/index.txt @@ -302,7 +302,7 @@ loop:: {% for field in form %} <div class="fieldWrapper"> {{ field.errors }} - {{ field.label_tag }}: {{ field }} + {{ field.label_tag }} {{ field }} </div> {% endfor %} <p><input type="submit" value="Send message" /></p> @@ -316,8 +316,14 @@ attributes, which can be useful in your templates: The label of the field, e.g. ``Email address``. ``{{ field.label_tag }}`` - The field's label wrapped in the appropriate HTML ``<label>`` tag, - e.g. ``<label for="id_email">Email address</label>`` + The field's label wrapped in the appropriate HTML ``<label>`` tag. + + .. versionchanged:: 1.6 + + This includes the form's :attr:`~django.forms.Form.label_suffix`. For + example, the default ``label_suffix`` is a semicolon:: + + <label for="id_email">Email address:</label> ``{{ field.value }}`` The value of the field. e.g ``someone@example.com`` @@ -375,7 +381,7 @@ these two methods:: {% for field in form.visible_fields %} <div class="fieldWrapper"> {{ field.errors }} - {{ field.label_tag }}: {{ field }} + {{ field.label_tag }} {{ field }} </div> {% endfor %} <p><input type="submit" value="Send message" /></p> @@ -403,7 +409,7 @@ using the :ttag:`include` tag to reuse it in other templates:: {% for field in form %} <div class="fieldWrapper"> {{ field.errors }} - {{ field.label_tag }}: {{ field }} + {{ field.label_tag }} {{ field }} </div> {% endfor %} diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index 4c46c6c0c0..d325a15cca 100644 --- a/docs/topics/forms/modelforms.txt +++ b/docs/topics/forms/modelforms.txt @@ -907,7 +907,7 @@ Third, you can manually render each field:: {{ formset.management_form }} {% for form in formset %} {% for field in form %} - {{ field.label_tag }}: {{ field }} + {{ field.label_tag }} {{ field }} {% endfor %} {% endfor %} </form> diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py index 4a9a203f50..637f643261 100644 --- a/tests/admin_util/tests.py +++ b/tests/admin_util/tests.py @@ -301,7 +301,7 @@ class UtilTests(SimpleTestCase): self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline"><i>text</i>:</label>') self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), - '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i></label>') + '<label for="id_cb" class="vCheckboxLabel required inline"><i>cb</i>:</label>') # normal strings needs to be escaped class MyForm(forms.Form): @@ -312,7 +312,7 @@ class UtilTests(SimpleTestCase): self.assertHTMLEqual(helpers.AdminField(form, 'text', is_first=False).label_tag(), '<label for="id_text" class="required inline">&text:</label>') self.assertHTMLEqual(helpers.AdminField(form, 'cb', is_first=False).label_tag(), - '<label for="id_cb" class="vCheckboxLabel required inline">&cb</label>') + '<label for="id_cb" class="vCheckboxLabel required inline">&cb:</label>') def test_flatten_fieldsets(self): """ diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index 1a3fb44a66..3b722e5ac1 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -1589,9 +1589,9 @@ class FormsTestCase(TestCase): # Recall from above that passing the "auto_id" argument to a Form gives each # field an "id" attribute. t = Template('''<form action=""> -<p>{{ form.username.label_tag }}: {{ form.username }}</p> -<p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> -<p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> +<p>{{ form.username.label_tag }} {{ form.username }}</p> +<p>{{ form.password1.label_tag }} {{ form.password1 }}</p> +<p>{{ form.password2.label_tag }} {{ form.password2 }}</p> <input type="submit" /> </form>''') self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action=""> @@ -1601,18 +1601,18 @@ class FormsTestCase(TestCase): <input type="submit" /> </form>""") self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id='id_%s')})), """<form action=""> -<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p> -<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> -<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> +<p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p> +<p><label for="id_password1">Password1:</label> <input type="password" name="password1" id="id_password1" /></p> +<p><label for="id_password2">Password2:</label> <input type="password" name="password2" id="id_password2" /></p> <input type="submit" /> </form>""") # User form.[field].help_text to output a field's help text. If the given field # does not have help text, nothing will be output. t = Template('''<form action=""> -<p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p> -<p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> -<p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> +<p>{{ form.username.label_tag }} {{ form.username }}<br />{{ form.username.help_text }}</p> +<p>{{ form.password1.label_tag }} {{ form.password1 }}</p> +<p>{{ form.password2.label_tag }} {{ form.password2 }}</p> <input type="submit" /> </form>''') self.assertHTMLEqual(t.render(Context({'form': UserRegistration(auto_id=False)})), """<form action=""> @@ -1819,17 +1819,17 @@ class FormsTestCase(TestCase): testcases = [ # (args, kwargs, expected) # without anything: just print the <label> - ((), {}, '<label for="id_field">Field</label>'), + ((), {}, '<label for="id_field">Field:</label>'), # passing just one argument: overrides the field's label - (('custom',), {}, '<label for="id_field">custom</label>'), + (('custom',), {}, '<label for="id_field">custom:</label>'), # the overriden label is escaped - (('custom&',), {}, '<label for="id_field">custom&</label>'), - ((mark_safe('custom&'),), {}, '<label for="id_field">custom&</label>'), + (('custom&',), {}, '<label for="id_field">custom&:</label>'), + ((mark_safe('custom&'),), {}, '<label for="id_field">custom&:</label>'), # Passing attrs to add extra attributes on the <label> - ((), {'attrs': {'class': 'pretty'}}, '<label for="id_field" class="pretty">Field</label>') + ((), {'attrs': {'class': 'pretty'}}, '<label for="id_field" class="pretty">Field:</label>') ] for args, kwargs, expected in testcases: @@ -1844,8 +1844,8 @@ class FormsTestCase(TestCase): field = CharField() boundfield = SomeForm(auto_id='')['field'] - self.assertHTMLEqual(boundfield.label_tag(), 'Field') - self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&') + self.assertHTMLEqual(boundfield.label_tag(), 'Field:') + self.assertHTMLEqual(boundfield.label_tag('Custom&'), 'Custom&:') def test_boundfield_label_tag_custom_widget_id_for_label(self): class CustomIdForLabelTextInput(TextInput): @@ -1861,5 +1861,5 @@ class FormsTestCase(TestCase): empty = CharField(widget=EmptyIdForLabelTextInput) form = SomeForm() - self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom</label>') - self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty</label>') + self.assertHTMLEqual(form['custom'].label_tag(), '<label for="custom_id_custom">Custom:</label>') + self.assertHTMLEqual(form['empty'].label_tag(), '<label>Empty:</label>') diff --git a/tests/forms_tests/tests/test_regressions.py b/tests/forms_tests/tests/test_regressions.py index ea138d32d5..d230d68f75 100644 --- a/tests/forms_tests/tests/test_regressions.py +++ b/tests/forms_tests/tests/test_regressions.py @@ -45,8 +45,8 @@ class FormsRegressionsTestCase(TransRealMixin, TestCase): field_2 = CharField(max_length=10, label=ugettext_lazy('field_2'), widget=TextInput(attrs={'id': 'field_2_id'})) f = SomeForm() - self.assertHTMLEqual(f['field_1'].label_tag(), '<label for="id_field_1">field_1</label>') - self.assertHTMLEqual(f['field_2'].label_tag(), '<label for="field_2_id">field_2</label>') + self.assertHTMLEqual(f['field_1'].label_tag(), '<label for="id_field_1">field_1:</label>') + self.assertHTMLEqual(f['field_2'].label_tag(), '<label for="field_2_id">field_2:</label>') # Unicode decoding problems... GENDERS = (('\xc5', 'En tied\xe4'), ('\xf8', 'Mies'), ('\xdf', 'Nainen')) |
