Refs #32339 -- Added use_fieldset to Widget.

This commit is contained in:
David 2022-01-13 23:08:38 +00:00 committed by Carlton Gibson
parent 04ad0f26ba
commit c8459708a7
28 changed files with 489 additions and 22 deletions

View File

@ -286,6 +286,13 @@ class BoundField:
r"widget$|input$", "", self.field.widget.__class__.__name__.lower() r"widget$|input$", "", self.field.widget.__class__.__name__.lower()
) )
@property
def use_fieldset(self):
"""
Return the value of this BoundField widget's use_fieldset attribute.
"""
return self.field.widget.use_fieldset
@html_safe @html_safe
class BoundWidget: class BoundWidget:

View File

@ -234,6 +234,7 @@ class Widget(metaclass=MediaDefiningClass):
is_localized = False is_localized = False
is_required = False is_required = False
supports_microseconds = True supports_microseconds = True
use_fieldset = False
def __init__(self, attrs=None): def __init__(self, attrs=None):
self.attrs = {} if attrs is None else attrs.copy() self.attrs = {} if attrs is None else attrs.copy()
@ -821,6 +822,7 @@ class RadioSelect(ChoiceWidget):
input_type = "radio" input_type = "radio"
template_name = "django/forms/widgets/radio.html" template_name = "django/forms/widgets/radio.html"
option_template_name = "django/forms/widgets/radio_option.html" option_template_name = "django/forms/widgets/radio_option.html"
use_fieldset = True
def id_for_label(self, id_, index=None): def id_for_label(self, id_, index=None):
""" """
@ -862,6 +864,7 @@ class MultiWidget(Widget):
""" """
template_name = "django/forms/widgets/multiwidget.html" template_name = "django/forms/widgets/multiwidget.html"
use_fieldset = True
def __init__(self, widgets, attrs=None): def __init__(self, widgets, attrs=None):
if isinstance(widgets, dict): if isinstance(widgets, dict):
@ -1027,6 +1030,7 @@ class SelectDateWidget(Widget):
input_type = "select" input_type = "select"
select_widget = Select select_widget = Select
date_re = _lazy_re_compile(r"(\d{4}|0)-(\d\d?)-(\d\d?)$") date_re = _lazy_re_compile(r"(\d{4}|0)-(\d\d?)-(\d\d?)$")
use_fieldset = True
def __init__(self, attrs=None, years=None, months=None, empty_label=None): def __init__(self, attrs=None, years=None, months=None, empty_label=None):
self.attrs = attrs or {} self.attrs = attrs or {}

View File

@ -1160,6 +1160,12 @@ Attributes of ``BoundField``
>>> print(f['message'].name) >>> print(f['message'].name)
message message
.. attribute:: BoundField.use_fieldset
.. versionadded:: 4.1
Returns the value of this BoundField widget's ``use_fieldset`` attribute.
.. attribute:: BoundField.widget_type .. attribute:: BoundField.widget_type
Returns the lowercased class name of the wrapped field's widget, with any Returns the lowercased class name of the wrapped field's widget, with any

View File

@ -315,6 +315,19 @@ foundation for custom widgets.
``<select multiple>`` don't appear in the data of an HTML form ``<select multiple>`` don't appear in the data of an HTML form
submission, so it's unknown whether or not the user submitted a value. submission, so it's unknown whether or not the user submitted a value.
.. attribute:: Widget.use_fieldset
.. versionadded:: 4.1
An attribute to identify if the widget should be grouped in a
``<fieldset>`` with a ``<legend>`` when rendered. Defaults to ``False``
but is ``True`` when the widget contains multiple ``<input>`` tags such as
:class:`~django.forms.CheckboxSelectMultiple`,
:class:`~django.forms.RadioSelect`,
:class:`~django.forms.MultiWidget`,
:class:`~django.forms.SplitDateTimeWidget`, and
:class:`~django.forms.SelectDateWidget`.
.. method:: use_required_attribute(initial) .. method:: use_required_attribute(initial)
Given a form field's ``initial`` value, returns whether or not the Given a form field's ``initial`` value, returns whether or not the

View File

@ -217,6 +217,10 @@ Forms
objects implement the ``__html__()`` method (typically when decorated with objects implement the ``__html__()`` method (typically when decorated with
the :func:`~django.utils.html.html_safe` decorator). the :func:`~django.utils.html.html_safe` decorator).
* The new :attr:`.BoundField.use_fieldset` and :attr:`.Widget.use_fieldset`
attributes help to identify widgets where its inputs should be grouped in a
``<fieldset>`` with a ``<legend>``.
Generic Views Generic Views
~~~~~~~~~~~~~ ~~~~~~~~~~~~~

View File

@ -686,6 +686,32 @@ Useful attributes on ``{{ field }}`` include:
<label for="id_email">Email address:</label> <label for="id_email">Email address:</label>
``{{ field.legend_tag }}``
.. versionadded:: 4.1
Similar to ``field.label_tag`` but uses a ``<legend>`` tag in place of
``<label>``, for widgets with multiple inputs wrapped in a ``<fieldset>``.
``{{ field.use_fieldset }}``
.. versionadded:: 4.1
This attribute is ``True`` if the form field's widget contains multiple
inputs that should be semantically grouped in a ``<fieldset>`` with a
``<legend>`` to improve accessibility. An example use in a template:
.. code-block:: html+django
{% if field.use_fieldset %}
<fieldset>
{% if field.label %}{{ field.legend_tag }}{% endif %}
{% else %}
{% if field.label %}{{ field.label_tag }}{% endif %}
{% endif %}
{{ field }}
{% if field.use_fieldset %}</fieldset>{% endif %}
``{{ field.value }}`` ``{{ field.value }}``
The value of the field. e.g ``someone@example.com``. The value of the field. e.g ``someone@example.com``.

View File

@ -0,0 +1,18 @@
{% for field, errors in fields %}
<div>
{% if field.use_fieldset %}
<fieldset>
{% if field.label %}{{ field.legend_tag }}{% endif %}
{% else %}
{% if field.label %}{{ field.label_tag }}{% endif %}
{% endif %}
{{ field }}
{% if field.use_fieldset %}</fieldset>{% endif %}
{% if forloop.last %}
{% for field in hidden_fields %}{{ field }}{% endfor %}
{% endif %}
</div>
{% endfor %}
{% if not fields and not errors %}
{% for field in hidden_fields %}{{ field }}{% endfor %}
{% endif %}

View File

@ -1,4 +1,4 @@
from django.forms import CheckboxInput from django.forms import BooleanField, CheckboxInput, Form
from .base import WidgetTest from .base import WidgetTest
@ -124,3 +124,16 @@ class CheckboxInputTest(WidgetTest):
attrs = {"checked": False} attrs = {"checked": False}
self.widget.get_context("name", True, attrs) self.widget.get_context("name", True, attrs)
self.assertIs(attrs["checked"], False) self.assertIs(attrs["checked"], False)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = BooleanField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
form.render(),
'<div><label for="id_field">Field:</label>'
'<input id="id_field" name="field" required type="checkbox"></div>',
)

View File

@ -1,7 +1,7 @@
import datetime import datetime
from django import forms from django import forms
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple, ChoiceField, Form
from django.test import override_settings from django.test import override_settings
from .base import WidgetTest from .base import WidgetTest
@ -254,3 +254,24 @@ class CheckboxSelectMultipleTest(WidgetTest):
self.assertEqual(bound_field.field.widget.id_for_label("id"), "") self.assertEqual(bound_field.field.widget.id_for_label("id"), "")
self.assertEqual(bound_field.label_tag(), "<label>F:</label>") self.assertEqual(bound_field.label_tag(), "<label>F:</label>")
self.assertEqual(bound_field.legend_tag(), "<legend>F:</legend>") self.assertEqual(bound_field.legend_tag(), "<legend>F:</legend>")
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = ChoiceField(widget=self.widget, choices=self.beatles)
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
form.render(),
'<div><fieldset><legend>Field:</legend><div id="id_field">'
'<div><label for="id_field_0"><input type="checkbox" '
'name="field" value="J" id="id_field_0"> John</label></div>'
'<div><label for="id_field_1"><input type="checkbox" '
'name="field" value="P" id="id_field_1">Paul</label></div>'
'<div><label for="id_field_2"><input type="checkbox" '
'name="field" value="G" id="id_field_2"> George</label></div>'
'<div><label for="id_field_3"><input type="checkbox" '
'name="field" value="R" id="id_field_3">'
"Ringo</label></div></div></fieldset></div>",
)

View File

@ -1,5 +1,5 @@
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import ClearableFileInput, MultiWidget from django.forms import ClearableFileInput, FileField, Form, MultiWidget
from .base import WidgetTest from .base import WidgetTest
@ -207,3 +207,28 @@ class ClearableFileInputTest(WidgetTest):
self.assertIs( self.assertIs(
widget.value_omitted_from_data({"field-clear": "y"}, {}, "field"), False widget.value_omitted_from_data({"field-clear": "y"}, {}, "field"), False
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = FileField(widget=self.widget)
with_file = FileField(widget=self.widget, initial=FakeFieldFile())
clearable_file = FileField(
widget=self.widget, initial=FakeFieldFile(), required=False
)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input id="id_field" name="field" type="file" required></div>'
'<div><label for="id_with_file">With file:</label>Currently: '
'<a href="something">something</a><br>Change:<input type="file" '
'name="with_file" id="id_with_file"></div>'
'<div><label for="id_clearable_file">Clearable file:</label>'
'Currently: <a href="something">something</a><input '
'type="checkbox" name="clearable_file-clear" id="clearable_file-clear_id">'
'<label for="clearable_file-clear_id">Clear</label><br>Change:'
'<input type="file" name="clearable_file" id="id_clearable_file"></div>',
form.render(),
)

View File

@ -1,6 +1,6 @@
from datetime import date from datetime import date
from django.forms import DateInput from django.forms import CharField, DateInput, Form
from django.utils import translation from django.utils import translation
from .base import WidgetTest from .base import WidgetTest
@ -60,3 +60,16 @@ class DateInputTest(WidgetTest):
date(2007, 9, 17), date(2007, 9, 17),
html='<input type="text" name="date" value="17.09.2007">', html='<input type="text" name="date" value="17.09.2007">',
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
form.render(),
'<div><label for="id_field">Field:</label>'
'<input id="id_field" name="field" required type="text"></div>',
)

View File

@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from django.forms import DateTimeInput from django.forms import CharField, DateTimeInput, Form
from django.test import ignore_warnings from django.test import ignore_warnings
from django.utils import translation from django.utils import translation
from django.utils.deprecation import RemovedInDjango50Warning from django.utils.deprecation import RemovedInDjango50Warning
@ -97,3 +97,16 @@ class DateTimeInputTest(WidgetTest):
d, d,
html='<input type="text" name="date" value="17/09/2007 12:51:34">', html='<input type="text" name="date" value="17/09/2007 12:51:34">',
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input id="id_field" name="field" required type="text"></div>',
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import FileInput from django.forms import FileField, FileInput, Form
from .base import WidgetTest from .base import WidgetTest
@ -35,3 +35,16 @@ class FileInputTest(WidgetTest):
# user to keep the existing, initial value. # user to keep the existing, initial value.
self.assertIs(self.widget.use_required_attribute(None), True) self.assertIs(self.widget.use_required_attribute(None), True)
self.assertIs(self.widget.use_required_attribute("resume.txt"), False) self.assertIs(self.widget.use_required_attribute("resume.txt"), False)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = FileField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label><input id="id_field" '
'name="field" required type="file"></div>',
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import HiddenInput from django.forms import CharField, Form, HiddenInput
from .base import WidgetTest from .base import WidgetTest
@ -17,3 +17,15 @@ class HiddenInputTest(WidgetTest):
self.assertIs(self.widget.use_required_attribute(None), False) self.assertIs(self.widget.use_required_attribute(None), False)
self.assertIs(self.widget.use_required_attribute(""), False) self.assertIs(self.widget.use_required_attribute(""), False)
self.assertIs(self.widget.use_required_attribute("foo"), False) self.assertIs(self.widget.use_required_attribute("foo"), False)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<input type="hidden" name="field" id="id_field">',
form.render(),
)

View File

@ -1,4 +1,5 @@
from django.forms import MultipleHiddenInput from django.forms import Form, MultipleChoiceField, MultipleHiddenInput
from django.utils.datastructures import MultiValueDict
from .base import WidgetTest from .base import WidgetTest
@ -104,3 +105,19 @@ class MultipleHiddenInputTest(WidgetTest):
'<input type="hidden" name="letters" value="c" id="hideme_2">' '<input type="hidden" name="letters" value="c" id="hideme_2">'
), ),
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
composers = MultipleChoiceField(
choices=[("J", "John Lennon"), ("P", "Paul McCartney")],
widget=MultipleHiddenInput,
)
form = TestForm(MultiValueDict({"composers": ["J", "P"]}))
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<input type="hidden" name="composers" value="J" id="id_composers_0">'
'<input type="hidden" name="composers" value="P" id="id_composers_1">',
form.render(),
)

View File

@ -4,6 +4,7 @@ from datetime import datetime
from django.forms import ( from django.forms import (
CharField, CharField,
FileInput, FileInput,
Form,
MultipleChoiceField, MultipleChoiceField,
MultiValueField, MultiValueField,
MultiWidget, MultiWidget,
@ -51,7 +52,9 @@ class ComplexField(MultiValueField):
MultipleChoiceField(choices=WidgetTest.beatles), MultipleChoiceField(choices=WidgetTest.beatles),
SplitDateTimeField(), SplitDateTimeField(),
) )
super().__init__(fields, required, widget, label, initial) super().__init__(
fields, required=required, widget=widget, label=label, initial=initial
)
def compress(self, data_list): def compress(self, data_list):
if data_list: if data_list:
@ -296,3 +299,22 @@ class MultiWidgetTest(WidgetTest):
# w2 ought to be independent of w1, since MultiWidget ought # w2 ought to be independent of w1, since MultiWidget ought
# to make a copy of its sub-widgets when it is copied. # to make a copy of its sub-widgets when it is copied.
self.assertEqual(w1.choices, [1, 2, 3]) self.assertEqual(w1.choices, [1, 2, 3])
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = ComplexField(widget=ComplexMultiWidget)
form = TestForm()
self.assertIs(form["field"].field.widget.use_fieldset, True)
self.assertHTMLEqual(
"<div><fieldset><legend>Field:</legend>"
'<input type="text" name="field_0" required id="id_field_0">'
'<select name="field_1" required id="id_field_1" multiple>'
'<option value="J">John</option><option value="P">Paul</option>'
'<option value="G">George</option><option value="R">Ringo</option></select>'
'<input type="text" name="field_2_0" required id="id_field_2_0">'
'<input type="text" name="field_2_1" required id="id_field_2_1">'
"</fieldset></div>",
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import NullBooleanSelect from django.forms import Form, NullBooleanField, NullBooleanSelect
from django.utils import translation from django.utils import translation
from .base import WidgetTest from .base import WidgetTest
@ -154,3 +154,19 @@ class NullBooleanSelectTest(WidgetTest):
""" """
), ),
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = NullBooleanField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<select name="field" id="id_field">'
'<option value="unknown" selected>Unknown</option>'
'<option value="true">Yes</option>'
'<option value="false">No</option></select></div>',
form.render(),
)

View File

@ -1,17 +1,32 @@
from django.forms.widgets import NumberInput from django.forms import CharField, Form, NumberInput
from django.test import override_settings from django.test import override_settings
from .base import WidgetTest from .base import WidgetTest
class NumberInputTests(WidgetTest): class NumberInputTests(WidgetTest):
widget = NumberInput(attrs={"max": 12345, "min": 1234, "step": 9999})
@override_settings(USE_THOUSAND_SEPARATOR=True) @override_settings(USE_THOUSAND_SEPARATOR=True)
def test_attrs_not_localized(self): def test_attrs_not_localized(self):
widget = NumberInput(attrs={"max": 12345, "min": 1234, "step": 9999})
self.check_html( self.check_html(
widget, self.widget,
"name", "name",
"value", "value",
'<input type="number" name="name" value="value" max="12345" min="1234" ' '<input type="number" name="name" value="value" max="12345" min="1234" '
'step="9999">', 'step="9999">',
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input id="id_field" max="12345" min="1234" '
'name="field" required step="9999" type="number"></div>',
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import PasswordInput from django.forms import CharField, Form, PasswordInput
from .base import WidgetTest from .base import WidgetTest
@ -37,3 +37,16 @@ class PasswordInputTest(WidgetTest):
"test@example.com", "test@example.com",
html='<input type="password" name="password" value="test@example.com">', html='<input type="password" name="password" value="test@example.com">',
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input type="password" name="field" required id="id_field"></div>',
form.render(),
)

View File

@ -1,6 +1,6 @@
import datetime import datetime
from django.forms import MultiWidget, RadioSelect from django.forms import ChoiceField, Form, MultiWidget, RadioSelect
from django.test import override_settings from django.test import override_settings
from .base import WidgetTest from .base import WidgetTest
@ -199,3 +199,26 @@ class RadioSelectTest(WidgetTest):
</div> </div>
""", """,
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = ChoiceField(
widget=self.widget, choices=self.beatles, required=False
)
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
'<div><fieldset><legend>Field:</legend><div id="id_field">'
'<div><label for="id_field_0">'
'<input type="radio" name="field" value="J" id="id_field_0"> John'
'</label></div><div><label for="id_field_1">'
'<input type="radio" name="field" value="P" id="id_field_1">Paul'
'</label></div><div><label for="id_field_2"><input type="radio" '
'name="field" value="G" id="id_field_2"> George</label></div>'
'<div><label for="id_field_3"><input type="radio" name="field" '
'value="R" id="id_field_3">Ringo</label></div></div></fieldset>'
"</div>",
form.render(),
)

View File

@ -1,7 +1,7 @@
import copy import copy
import datetime import datetime
from django.forms import Select from django.forms import ChoiceField, Form, Select
from django.test import override_settings from django.test import override_settings
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -485,3 +485,20 @@ class SelectTest(WidgetTest):
def test_doesnt_render_required_when_no_choices_are_available(self): def test_doesnt_render_required_when_no_choices_are_available(self):
widget = self.widget(choices=[]) widget = self.widget(choices=[])
self.assertIs(widget.use_required_attribute(initial=None), False) self.assertIs(widget.use_required_attribute(initial=None), False)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = ChoiceField(widget=self.widget, choices=self.beatles)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<select name="field" id="id_field">'
'<option value="J">John</option> '
'<option value="P">Paul</option>'
'<option value="G">George</option>'
'<option value="R">Ringo</option></select></div>',
form.render(),
)

View File

@ -707,3 +707,46 @@ class SelectDateWidgetTest(WidgetTest):
""" """
), ),
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = DateField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
'<div><fieldset><legend for="id_field_month">Field:</legend>'
'<select name="field_month" required id="id_field_month">'
'<option value="1">January</option><option value="2">February</option>'
'<option value="3">March</option><option value="4">April</option>'
'<option value="5">May</option><option value="6">June</option>'
'<option value="7">July</option><option value="8">August</option>'
'<option value="9">September</option><option value="10">October</option>'
'<option value="11">November</option><option value="12">December</option>'
'</select><select name="field_day" required id="id_field_day">'
'<option value="1">1</option><option value="2">2</option>'
'<option value="3">3</option><option value="4">4</option>'
'<option value="5">5</option><option value="6">6</option>'
'<option value="7">7</option><option value="8">8</option>'
'<option value="9">9</option><option value="10">10</option>'
'<option value="11">11</option><option value="12">12</option>'
'<option value="13">13</option><option value="14">14</option>'
'<option value="15">15</option><option value="16">16</option>'
'<option value="17">17</option><option value="18">18</option>'
'<option value="19">19</option><option value="20">20</option>'
'<option value="21">21</option><option value="22">22</option>'
'<option value="23">23</option><option value="24">24</option>'
'<option value="25">25</option><option value="26">26</option>'
'<option value="27">27</option><option value="28">28</option>'
'<option value="29">29</option><option value="30">30</option>'
'<option value="31">31</option></select>'
'<select name="field_year" required id="id_field_year">'
'<option value="2007">2007</option><option value="2008">2008</option>'
'<option value="2009">2009</option><option value="2010">2010</option>'
'<option value="2011">2011</option><option value="2012">2012</option>'
'<option value="2013">2013</option><option value="2014">2014</option>'
'<option value="2015">2015</option><option value="2016">2016</option>'
"</select></fieldset></div>",
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import SelectMultiple from django.forms import ChoiceField, Form, SelectMultiple
from .base import WidgetTest from .base import WidgetTest
@ -190,3 +190,21 @@ class SelectMultipleTest(WidgetTest):
self.assertIs( self.assertIs(
widget.value_omitted_from_data({"field": "value"}, {}, "field"), False widget.value_omitted_from_data({"field": "value"}, {}, "field"), False
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = ChoiceField(
widget=self.widget, choices=self.beatles, required=False
)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<select multiple name="field" id="id_field">'
'<option value="J">John</option> <option value="P">Paul</option>'
'<option value="G">George</option><option value="R">Ringo'
"</option></select></div>",
form.render(),
)

View File

@ -1,6 +1,6 @@
from datetime import date, datetime, time from datetime import date, datetime, time
from django.forms import SplitDateTimeWidget from django.forms import Form, SplitDateTimeField, SplitDateTimeWidget
from .base import WidgetTest from .base import WidgetTest
@ -94,3 +94,26 @@ class SplitDateTimeWidgetTest(WidgetTest):
'<input type="text" name="date_1" value="07:30">' '<input type="text" name="date_1" value="07:30">'
), ),
) )
self.check_html(
widget,
"date",
datetime(2006, 1, 10, 7, 30),
html=(
'<input type="text" name="date_0" value="10/01/2006">'
'<input type="text" name="date_1" value="07:30">'
),
)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = SplitDateTimeField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
'<div><fieldset><legend>Field:</legend><input type="text" '
'name="field_0" required id="id_field_0"><input type="text" '
'name="field_1" required id="id_field_1"></fieldset></div>',
form.render(),
)

View File

@ -1,6 +1,6 @@
from datetime import datetime from datetime import datetime
from django.forms import SplitHiddenDateTimeWidget from django.forms import Form, SplitDateTimeField, SplitHiddenDateTimeWidget
from django.utils import translation from django.utils import translation
from .base import WidgetTest from .base import WidgetTest
@ -81,3 +81,35 @@ class SplitHiddenDateTimeWidgetTest(WidgetTest):
time_attrs={"class": "bar"}, attrs={"class": "foo"} time_attrs={"class": "bar"}, attrs={"class": "foo"}
) )
self.check_html(widget, "date", datetime(2006, 1, 10, 7, 30), html=html) self.check_html(widget, "date", datetime(2006, 1, 10, 7, 30), html=html)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = SplitDateTimeField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
'<input type="hidden" name="field_0" id="id_field_0">'
'<input type="hidden" name="field_1" id="id_field_1">',
form.render(),
)
def test_fieldset_with_unhidden_field(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
hidden_field = SplitDateTimeField(widget=self.widget)
unhidden_field = SplitDateTimeField()
form = TestForm()
self.assertIs(self.widget.use_fieldset, True)
self.assertHTMLEqual(
"<div><fieldset><legend>Unhidden field:</legend>"
'<input type="text" name="unhidden_field_0" required '
'id="id_unhidden_field_0"><input type="text" '
'name="unhidden_field_1" required id="id_unhidden_field_1">'
'</fieldset><input type="hidden" name="hidden_field_0" '
'id="id_hidden_field_0"><input type="hidden" '
'name="hidden_field_1" id="id_hidden_field_1"></div>',
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import Textarea from django.forms import CharField, Form, Textarea
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from .base import WidgetTest from .base import WidgetTest
@ -62,3 +62,17 @@ class TextareaTest(WidgetTest):
"</textarea>" "</textarea>"
), ),
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<textarea cols="40" id="id_field" name="field" '
'required rows="10"></textarea></div>',
form.render(),
)

View File

@ -1,4 +1,4 @@
from django.forms import TextInput from django.forms import CharField, Form, TextInput
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from .base import WidgetTest from .base import WidgetTest
@ -119,3 +119,16 @@ class TextInputTest(WidgetTest):
self.assertIs(self.widget.use_required_attribute(None), True) self.assertIs(self.widget.use_required_attribute(None), True)
self.assertIs(self.widget.use_required_attribute(""), True) self.assertIs(self.widget.use_required_attribute(""), True)
self.assertIs(self.widget.use_required_attribute("resume.txt"), True) self.assertIs(self.widget.use_required_attribute("resume.txt"), True)
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input type="text" name="field" required id="id_field"></div>',
form.render(),
)

View File

@ -1,6 +1,6 @@
from datetime import time from datetime import time
from django.forms import TimeInput from django.forms import CharField, Form, TimeInput
from django.utils import translation from django.utils import translation
from .base import WidgetTest from .base import WidgetTest
@ -67,3 +67,16 @@ class TimeInputTest(WidgetTest):
t, t,
html='<input type="text" name="time" value="12:51:34">', html='<input type="text" name="time" value="12:51:34">',
) )
def test_fieldset(self):
class TestForm(Form):
template_name = "forms_tests/use_fieldset.html"
field = CharField(widget=self.widget)
form = TestForm()
self.assertIs(self.widget.use_fieldset, False)
self.assertHTMLEqual(
'<div><label for="id_field">Field:</label>'
'<input id="id_field" name="field" required type="text"></div>',
form.render(),
)