Fixed #22533 -- Added label_suffix parameter to form fields.

Fields can now receive the `label_suffix` attribute, which will override
a form's `label_suffix`.

This enhances the possibility to customize form's `label_suffix`, allowing
to use such customizations while using shortcuts such as
`{{ form.as_p }}`.

Note that the field's own customization can be overridden at runtime by
using the `label_prefix` parameter to `BoundField.label_tag()`.

Refs #18134.
This commit is contained in:
Julen Ruiz Aizpuru 2014-04-29 10:07:57 +02:00 committed by Tim Graham
parent f2a8e47cfd
commit 5eb81ce445
6 changed files with 58 additions and 14 deletions

View File

@ -61,7 +61,7 @@ class Field(object):
def __init__(self, required=True, widget=None, label=None, initial=None,
help_text='', error_messages=None, show_hidden_initial=False,
validators=[], localize=False):
validators=[], localize=False, label_suffix=None):
# required -- Boolean that specifies whether the field is required.
# True by default.
# widget -- A Widget class, or instance of a Widget class, that should
@ -81,9 +81,12 @@ class Field(object):
# hidden widget with initial value after widget.
# validators -- List of addtional validators to use
# localize -- Boolean that specifies if the field should be localized.
# label_suffix -- Suffix to be added to the label. Overrides
# form's label_suffix.
self.required, self.label, self.initial = required, label, initial
self.show_hidden_initial = show_hidden_initial
self.help_text = help_text
self.label_suffix = label_suffix
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()

View File

@ -616,8 +616,10 @@ class BoundField(object):
label_suffix allows overriding the form's label_suffix.
"""
contents = contents or self.label
if label_suffix is None:
label_suffix = (self.field.label_suffix if self.field.label_suffix is not None
else self.form.label_suffix)
# Only add the suffix if the label does not end in punctuation.
label_suffix = label_suffix if label_suffix is not None else self.form.label_suffix
# Translators: If found as last label character, these punctuation
# characters will prevent the default label_suffix to be appended to the label
if label_suffix and contents and contents[-1] not in _(':?.!'):

View File

@ -652,8 +652,13 @@ Note that the label suffix is added only if the last character of the
label isn't a punctuation character (in English, those are ``.``, ``!``, ``?``
or ``:``).
You can also customize the ``label_suffix`` on a per-field basis using the
``label_suffix`` parameter to :meth:`~django.forms.BoundField.label_tag`.
.. versionadded:: 1.8
Fields can also define their own :attr:`~django.forms.Field.label_suffix`.
This will take precedence over :attr:`Form.label_suffix
<django.forms.Form.label_suffix>`. The suffix can also be overridden at runtime
using the ``label_suffix`` parameter to
:meth:`~django.forms.BoundField.label_tag`.
Notes on field ordering
~~~~~~~~~~~~~~~~~~~~~~~
@ -799,12 +804,12 @@ auto-generated label tag. An optional ``attrs`` dictionary may contain
additional attributes for the ``<label>`` tag.
The HTML that's generated includes the form's
:attr:`~django.forms.Form.label_suffix` (a colon, by default). The optional
``label_suffix`` parameter allows you to override the form's
:attr:`~django.forms.Form.label_suffix`. For example, you can use an empty
string to hide the label on selected fields. If you need to do this in a
template, you could write a custom filter to allow passing parameters to
``label_tag``.
:attr:`~django.forms.Form.label_suffix` (a colon, by default) or, if set, the
current field's :attr:`~django.forms.Field.label_suffix`. The optional
``label_suffix`` parameter allows you to override any previously set
suffix. For example, you can use an empty string to hide the label on selected
fields. If you need to do this in a template, you could write a custom
filter to allow passing parameters to ``label_tag``.
.. versionchanged:: 1.8

View File

@ -119,6 +119,26 @@ We've specified ``auto_id=False`` to simplify the output::
<tr><th>Your Web site:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
``label_suffix``
~~~~~~~~~~~~~~~~
.. attribute:: Field.label_suffix
.. versionadded:: 1.8
The ``label_suffix`` argument lets you override the form's
:attr:`~django.forms.Form.label_suffix` on a per-field basis::
>>> class ContactForm(forms.Form):
... age = forms.IntegerField()
... nationality = forms.CharField()
... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
>>> f = ContactForm(label_suffix='?')
>>> print(f.as_p())
<p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" /></p>
<p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" /></p>
<p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" /></p>
``initial``
~~~~~~~~~~~

View File

@ -118,6 +118,13 @@ Forms
the ``<label>`` tags for required fields will have this class present in its
attributes.
* :class:`~django.forms.Field` now accepts a
:attr:`~django.forms.Field.label_suffix` argument, which will override the
form's :attr:`~django.forms.Form.label_suffix`. This enables customizing the
suffix on a per-field basis — previously it wasn't possible to override
a form's :attr:`~django.forms.Form.label_suffix` while using shortcuts such
as ``{{ form.as_p }}`` in templates.
Internationalization
^^^^^^^^^^^^^^^^^^^^

View File

@ -1100,18 +1100,25 @@ class FormsTestCase(TestCase):
class FavoriteForm(Form):
color = CharField(label='Favorite color?')
animal = CharField(label='Favorite animal')
answer = CharField(label='Secret answer', label_suffix=' =')
f = FavoriteForm(auto_id=False)
self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
<li>Favorite animal: <input type="text" name="animal" /></li>""")
<li>Favorite animal: <input type="text" name="animal" /></li>
<li>Secret answer = <input type="text" name="answer" /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='?')
self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
<li>Favorite animal? <input type="text" name="animal" /></li>""")
<li>Favorite animal? <input type="text" name="animal" /></li>
<li>Secret answer = <input type="text" name="answer" /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='')
self.assertHTMLEqual(f.as_ul(), """<li>Favorite color? <input type="text" name="color" /></li>
<li>Favorite animal <input type="text" name="animal" /></li>""")
<li>Favorite animal <input type="text" name="animal" /></li>
<li>Secret answer = <input type="text" name="answer" /></li>""")
f = FavoriteForm(auto_id=False, label_suffix='\u2192')
self.assertHTMLEqual(f.as_ul(), '<li>Favorite color? <input type="text" name="color" /></li>\n<li>Favorite animal\u2192 <input type="text" name="animal" /></li>')
self.assertHTMLEqual(f.as_ul(), '<li>Favorite color? <input type="text" name="color" /></li>\n<li>Favorite animal\u2192 <input type="text" name="animal" /></li>\n<li>Secret answer = <input type="text" name="answer" /></li>')
def test_initial_data(self):
# You can specify initial data for a field by using the 'initial' argument to a