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, def __init__(self, required=True, widget=None, label=None, initial=None,
help_text='', error_messages=None, show_hidden_initial=False, 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. # required -- Boolean that specifies whether the field is required.
# True by default. # True by default.
# widget -- A Widget class, or instance of a Widget class, that should # 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. # hidden widget with initial value after widget.
# validators -- List of addtional validators to use # validators -- List of addtional validators to use
# localize -- Boolean that specifies if the field should be localized. # 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.required, self.label, self.initial = required, label, initial
self.show_hidden_initial = show_hidden_initial self.show_hidden_initial = show_hidden_initial
self.help_text = help_text self.help_text = help_text
self.label_suffix = label_suffix
widget = widget or self.widget widget = widget or self.widget
if isinstance(widget, type): if isinstance(widget, type):
widget = widget() widget = widget()

View File

@ -616,8 +616,10 @@ class BoundField(object):
label_suffix allows overriding the form's label_suffix. label_suffix allows overriding the form's label_suffix.
""" """
contents = contents or self.label 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. # 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 # Translators: If found as last label character, these punctuation
# characters will prevent the default label_suffix to be appended to the label # characters will prevent the default label_suffix to be appended to the label
if label_suffix and contents and contents[-1] not in _(':?.!'): 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 ``.``, ``!``, ``?`` label isn't a punctuation character (in English, those are ``.``, ``!``, ``?``
or ``:``). or ``:``).
You can also customize the ``label_suffix`` on a per-field basis using the .. versionadded:: 1.8
``label_suffix`` parameter to :meth:`~django.forms.BoundField.label_tag`.
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 Notes on field ordering
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@ -799,12 +804,12 @@ auto-generated label tag. An optional ``attrs`` dictionary may contain
additional attributes for the ``<label>`` tag. additional attributes for the ``<label>`` tag.
The HTML that's generated includes the form's The HTML that's generated includes the form's
:attr:`~django.forms.Form.label_suffix` (a colon, by default). The optional :attr:`~django.forms.Form.label_suffix` (a colon, by default) or, if set, the
``label_suffix`` parameter allows you to override the form's current field's :attr:`~django.forms.Field.label_suffix`. The optional
:attr:`~django.forms.Form.label_suffix`. For example, you can use an empty ``label_suffix`` parameter allows you to override any previously set
string to hide the label on selected fields. If you need to do this in a suffix. For example, you can use an empty string to hide the label on selected
template, you could write a custom filter to allow passing parameters to fields. If you need to do this in a template, you could write a custom
``label_tag``. filter to allow passing parameters to ``label_tag``.
.. versionchanged:: 1.8 .. 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>Your Web site:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></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`` ``initial``
~~~~~~~~~~~ ~~~~~~~~~~~

View File

@ -118,6 +118,13 @@ Forms
the ``<label>`` tags for required fields will have this class present in its the ``<label>`` tags for required fields will have this class present in its
attributes. 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 Internationalization
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^

View File

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