diff options
| author | David Smith <smithdc@gmail.com> | 2021-06-11 07:39:12 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2021-08-27 06:14:01 +0200 |
| commit | 5942ab5eb165ee2e759174e297148a40dd855920 (patch) | |
| tree | 6018ad2e699cc2bac292c377bbbd86ea9fc99a89 | |
| parent | a5cb1ef6eb842c38627ff6685b977fd42a342b67 (diff) | |
Refs #32338 -- Made RadioSelect/CheckboxSelectMultiple render in <div> tags.
This improves accessibility for screen reader users.
| -rw-r--r-- | django/forms/jinja2/django/forms/widgets/multiple_input.html | 10 | ||||
| -rw-r--r-- | django/forms/templates/django/forms/widgets/multiple_input.html | 10 | ||||
| -rw-r--r-- | docs/ref/forms/widgets.txt | 32 | ||||
| -rw-r--r-- | docs/releases/4.0.txt | 7 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_forms.py | 108 | ||||
| -rw-r--r-- | tests/forms_tests/tests/test_i18n.py | 22 | ||||
| -rw-r--r-- | tests/forms_tests/widget_tests/test_checkboxselectmultiple.py | 175 | ||||
| -rw-r--r-- | tests/forms_tests/widget_tests/test_radioselect.py | 132 | ||||
| -rw-r--r-- | tests/model_forms/test_modelchoicefield.py | 26 |
9 files changed, 258 insertions, 264 deletions
diff --git a/django/forms/jinja2/django/forms/widgets/multiple_input.html b/django/forms/jinja2/django/forms/widgets/multiple_input.html index 21cd9b665d..aee0bd6852 100644 --- a/django/forms/jinja2/django/forms/widgets/multiple_input.html +++ b/django/forms/jinja2/django/forms/widgets/multiple_input.html @@ -1,5 +1,5 @@ -{% set id = widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} - <li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for widget in options %} - <li>{% include widget.template_name %}</li>{% endfor %}{% if group %} - </ul></li>{% endif %}{% endfor %} -</ul> +{% set id = widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} + <div><label>{{ group }}</label>{% endif %}{% for widget in options %}<div> + {% include widget.template_name %}</div>{% endfor %}{% if group %} + </div>{% endif %}{% endfor %} +</div> diff --git a/django/forms/templates/django/forms/widgets/multiple_input.html b/django/forms/templates/django/forms/widgets/multiple_input.html index 0ba9942874..2a0fec6ecc 100644 --- a/django/forms/templates/django/forms/widgets/multiple_input.html +++ b/django/forms/templates/django/forms/widgets/multiple_input.html @@ -1,5 +1,5 @@ -{% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} - <li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %} - <li>{% include option.template_name with widget=option %}</li>{% endfor %}{% if group %} - </ul></li>{% endif %}{% endfor %} -</ul>{% endwith %} +{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} + <div><label>{{ group }}</label>{% endif %}{% for option in options %}<div> + {% include option.template_name with widget=option %}</div>{% endfor %}{% if group %} + </div>{% endif %}{% endfor %} +</div>{% endwith %} diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index 48e83a2da9..970e30456c 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -703,14 +703,19 @@ that specifies the template used to render each choice. For example, for the * ``option_template_name``: ``'django/forms/widgets/radio_option.html'`` Similar to :class:`Select`, but rendered as a list of radio buttons within - ``<li>`` tags: + ``<div>`` tags: .. code-block:: html - <ul> - <li><input type="radio" name="..."></li> + <div> + <div><input type="radio" name="..."></div> ... - </ul> + </div> + + .. versionchanged:: 4.0 + + So they are announced more concisely by screen readers, radio buttons + were changed to render in ``<div>`` tags. For more granular control over the generated markup, you can loop over the radio buttons in the template. Assuming a form ``myform`` with a field @@ -788,10 +793,10 @@ that specifies the template used to render each choice. For example, for the </fieldset> If you decide not to loop over the radio buttons -- e.g., if your template - includes ``{{ myform.beatles }}`` -- they'll be output in a ``<ul>`` with - ``<li>`` tags, as above. + includes ``{{ myform.beatles }}`` -- they'll be output in a ``<div>`` with + ``<div>`` tags, as above. - The outer ``<ul>`` container receives the ``id`` attribute of the widget, + The outer ``<div>`` container receives the ``id`` attribute of the widget, if defined, or :attr:`BoundField.auto_id` otherwise. When looping over the radio buttons, the ``label`` and ``input`` tags include @@ -810,14 +815,19 @@ that specifies the template used to render each choice. For example, for the .. code-block:: html - <ul> - <li><input type="checkbox" name="..." ></li> + <div> + <div><input type="checkbox" name="..." ></div> ... - </ul> + </div> - The outer ``<ul>`` container receives the ``id`` attribute of the widget, + The outer ``<div>`` container receives the ``id`` attribute of the widget, if defined, or :attr:`BoundField.auto_id` otherwise. + .. versionchanged:: 4.0 + + So they are announced more concisely by screen readers, checkboxes were + changed to render in ``<div>`` tags. + Like :class:`RadioSelect`, you can loop over the individual checkboxes for the widget's choices. Unlike :class:`RadioSelect`, the checkboxes won't include the ``required`` HTML attribute if the field is required because browser validation diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index aa45d1e1e9..45743c4139 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -551,6 +551,13 @@ Miscellaneous ``django.db.migrations.state.ProjectState.__init__()`` method must now be a set if provided. +* :class:`~django.forms.RadioSelect` and + :class:`~django.forms.CheckboxSelectMultiple` widgets are now rendered in + ``<div>`` tags so they are announced more concisely by screen readers. If you + need the previous behavior, :ref:`override the widget template + <overriding-built-in-widget-templates>` with the appropriate template from + Django 3.2. + .. _deprecated-features-4.0: Features deprecated in 4.0 diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py index 212af2ad14..83dc5fec20 100644 --- a/tests/forms_tests/tests/test_forms.py +++ b/tests/forms_tests/tests/test_forms.py @@ -585,20 +585,20 @@ class FormsTestCase(SimpleTestCase): language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect) f = FrameworkForm(auto_id=False) - self.assertHTMLEqual(str(f['language']), """<ul> -<li><label><input type="radio" name="language" value="P" required> Python</label></li> -<li><label><input type="radio" name="language" value="J" required> Java</label></li> -</ul>""") + self.assertHTMLEqual(str(f['language']), """<div> +<div><label><input type="radio" name="language" value="P" required> Python</label></div> +<div><label><input type="radio" name="language" value="J" required> Java</label></div> +</div>""") self.assertHTMLEqual(f.as_table(), """<tr><th>Name:</th><td><input type="text" name="name" required></td></tr> -<tr><th>Language:</th><td><ul> -<li><label><input type="radio" name="language" value="P" required> Python</label></li> -<li><label><input type="radio" name="language" value="J" required> Java</label></li> -</ul></td></tr>""") +<tr><th>Language:</th><td><div> +<div><label><input type="radio" name="language" value="P" required> Python</label></div> +<div><label><input type="radio" name="language" value="J" required> Java</label></div> +</div></td></tr>""") self.assertHTMLEqual(f.as_ul(), """<li>Name: <input type="text" name="name" required></li> -<li>Language: <ul> -<li><label><input type="radio" name="language" value="P" required> Python</label></li> -<li><label><input type="radio" name="language" value="J" required> Java</label></li> -</ul></li>""") +<li>Language: <div> +<div><label><input type="radio" name="language" value="P" required> Python</label></div> +<div><label><input type="radio" name="language" value="J" required> Java</label></div> +</div></li>""") # Regarding auto_id and <label>, RadioSelect is a special case. Each radio button # gets a distinct ID, formed by appending an underscore plus the button's @@ -606,12 +606,12 @@ class FormsTestCase(SimpleTestCase): f = FrameworkForm(auto_id='id_%s') self.assertHTMLEqual( str(f['language']), - """<ul id="id_language"> -<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> -Python</label></li> -<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> -Java</label></li> -</ul>""" + """<div id="id_language"> +<div><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> +Python</label></div> +<div><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> +Java</label></div> +</div>""" ) # When RadioSelect is used with auto_id, and the whole form is printed @@ -621,32 +621,32 @@ Java</label></li> self.assertHTMLEqual( f.as_table(), """<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" required></td></tr> -<tr><th><label>Language:</label></th><td><ul id="id_language"> -<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> -Python</label></li> -<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> -Java</label></li> -</ul></td></tr>""" +<tr><th><label>Language:</label></th><td><div id="id_language"> +<div><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> +Python</label></div> +<div><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> +Java</label></div> +</div></td></tr>""" ) self.assertHTMLEqual( f.as_ul(), """<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required></li> -<li><label>Language:</label> <ul id="id_language"> -<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> -Python</label></li> -<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> -Java</label></li> -</ul></li>""" +<li><label>Language:</label> <div id="id_language"> +<div><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> +Python</label></div> +<div><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> +Java</label></div> +</div></li>""" ) self.assertHTMLEqual( f.as_p(), """<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required></p> -<p><label>Language:</label> <ul id="id_language"> -<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> -Python</label></li> -<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> -Java</label></li> -</ul></p>""" +<p><label>Language:</label> <div id="id_language"> +<div><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required> +Python</label></div> +<div><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required> +Java</label></div> +</div></p>""" ) # Test iterating on individual radios in a template @@ -870,20 +870,20 @@ Java</label></li> ) f = SongForm(auto_id=False) - self.assertHTMLEqual(str(f['composers']), """<ul> -<li><label><input type="checkbox" name="composers" value="J"> John Lennon</label></li> -<li><label><input type="checkbox" name="composers" value="P"> Paul McCartney</label></li> -</ul>""") + self.assertHTMLEqual(str(f['composers']), """<div> +<div><label><input type="checkbox" name="composers" value="J"> John Lennon</label></div> +<div><label><input type="checkbox" name="composers" value="P"> Paul McCartney</label></div> +</div>""") f = SongForm({'composers': ['J']}, auto_id=False) - self.assertHTMLEqual(str(f['composers']), """<ul> -<li><label><input checked type="checkbox" name="composers" value="J"> John Lennon</label></li> -<li><label><input type="checkbox" name="composers" value="P"> Paul McCartney</label></li> -</ul>""") + self.assertHTMLEqual(str(f['composers']), """<div> +<div><label><input checked type="checkbox" name="composers" value="J"> John Lennon</label></div> +<div><label><input type="checkbox" name="composers" value="P"> Paul McCartney</label></div> +</div>""") f = SongForm({'composers': ['J', 'P']}, auto_id=False) - self.assertHTMLEqual(str(f['composers']), """<ul> -<li><label><input checked type="checkbox" name="composers" value="J"> John Lennon</label></li> -<li><label><input checked type="checkbox" name="composers" value="P"> Paul McCartney</label></li> -</ul>""") + self.assertHTMLEqual(str(f['composers']), """<div> +<div><label><input checked type="checkbox" name="composers" value="J"> John Lennon</label></div> +<div><label><input checked type="checkbox" name="composers" value="P"> Paul McCartney</label></div> +</div>""") # Test iterating on individual checkboxes in a template t = Template('{% for checkbox in form.composers %}<div class="mycheckbox">{{ checkbox }}</div>{% endfor %}') self.assertHTMLEqual(t.render(Context({'form': f})), """<div class="mycheckbox"><label> @@ -905,12 +905,12 @@ Java</label></li> f = SongForm(auto_id='%s_id') self.assertHTMLEqual( str(f['composers']), - """<ul id="composers_id"> -<li><label for="composers_id_0"> -<input type="checkbox" name="composers" value="J" id="composers_id_0"> John Lennon</label></li> -<li><label for="composers_id_1"> -<input type="checkbox" name="composers" value="P" id="composers_id_1"> Paul McCartney</label></li> -</ul>""" + """<div id="composers_id"> +<div><label for="composers_id_0"> +<input type="checkbox" name="composers" value="J" id="composers_id_0"> John Lennon</label></div> +<div><label for="composers_id_1"> +<input type="checkbox" name="composers" value="P" id="composers_id_1"> Paul McCartney</label></div> +</div>""" ) def test_multiple_choice_list_data(self): diff --git a/tests/forms_tests/tests/test_i18n.py b/tests/forms_tests/tests/test_i18n.py index ec1f323f1a..d941902af2 100644 --- a/tests/forms_tests/tests/test_i18n.py +++ b/tests/forms_tests/tests/test_i18n.py @@ -57,15 +57,15 @@ class FormsI18nTests(SimpleTestCase): self.assertHTMLEqual( f.as_p(), '<p><label>\xc5\xf8\xdf:</label>' - '<ul id="id_somechoice">\n' - '<li><label for="id_somechoice_0">' + '<div id="id_somechoice">\n' + '<div><label for="id_somechoice_0">' '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required> ' - 'En tied\xe4</label></li>\n' - '<li><label for="id_somechoice_1">' + 'En tied\xe4</label></div>\n' + '<div><label for="id_somechoice_1">' '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" required> ' - 'Mies</label></li>\n<li><label for="id_somechoice_2">' + 'Mies</label></div>\n<div><label for="id_somechoice_2">' '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" required> ' - 'Nainen</label></li>\n</ul></p>' + 'Nainen</label></div>\n</div></p>' ) # Translated error messages @@ -77,14 +77,14 @@ class FormsI18nTests(SimpleTestCase): '\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c' '\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n' '<p><label>\xc5\xf8\xdf:</label>' - ' <ul id="id_somechoice">\n<li><label for="id_somechoice_0">' + ' <div id="id_somechoice">\n<div><label for="id_somechoice_0">' '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required> ' - 'En tied\xe4</label></li>\n' - '<li><label for="id_somechoice_1">' + 'En tied\xe4</label></div>\n' + '<div><label for="id_somechoice_1">' '<input type="radio" id="id_somechoice_1" value="\xf8" name="somechoice" required> ' - 'Mies</label></li>\n<li><label for="id_somechoice_2">' + 'Mies</label></div>\n<div><label for="id_somechoice_2">' '<input type="radio" id="id_somechoice_2" value="\xdf" name="somechoice" required> ' - 'Nainen</label></li>\n</ul></p>' + 'Nainen</label></div>\n</div></p>' ) def test_select_translated_text(self): diff --git a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py index 42555d98a6..05406894dd 100644 --- a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py +++ b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py @@ -11,39 +11,39 @@ class CheckboxSelectMultipleTest(WidgetTest): widget = CheckboxSelectMultiple def test_render_value(self): - self.check_html(self.widget(choices=self.beatles), 'beatles', ['J'], html=( - """<ul> - <li><label><input checked type="checkbox" name="beatles" value="J"> John</label></li> - <li><label><input type="checkbox" name="beatles" value="P"> Paul</label></li> - <li><label><input type="checkbox" name="beatles" value="G"> George</label></li> - <li><label><input type="checkbox" name="beatles" value="R"> Ringo</label></li> - </ul>""" - )) + self.check_html(self.widget(choices=self.beatles), 'beatles', ['J'], html=""" + <div> + <div><label><input checked type="checkbox" name="beatles" value="J"> John</label></div> + <div><label><input type="checkbox" name="beatles" value="P"> Paul</label></div> + <div><label><input type="checkbox" name="beatles" value="G"> George</label></div> + <div><label><input type="checkbox" name="beatles" value="R"> Ringo</label></div> + </div> + """) def test_render_value_multiple(self): - self.check_html(self.widget(choices=self.beatles), 'beatles', ['J', 'P'], html=( - """<ul> - <li><label><input checked type="checkbox" name="beatles" value="J"> John</label></li> - <li><label><input checked type="checkbox" name="beatles" value="P"> Paul</label></li> - <li><label><input type="checkbox" name="beatles" value="G"> George</label></li> - <li><label><input type="checkbox" name="beatles" value="R"> Ringo</label></li> - </ul>""" - )) + self.check_html(self.widget(choices=self.beatles), 'beatles', ['J', 'P'], html=""" + <div> + <div><label><input checked type="checkbox" name="beatles" value="J"> John</label></div> + <div><label><input checked type="checkbox" name="beatles" value="P"> Paul</label></div> + <div><label><input type="checkbox" name="beatles" value="G"> George</label></div> + <div><label><input type="checkbox" name="beatles" value="R"> Ringo</label></div> + </div> + """) def test_render_none(self): """ If the value is None, none of the options are selected, even if the choices have an empty option. """ - self.check_html(self.widget(choices=(('', 'Unknown'),) + self.beatles), 'beatles', None, html=( - """<ul> - <li><label><input type="checkbox" name="beatles" value=""> Unknown</label></li> - <li><label><input type="checkbox" name="beatles" value="J"> John</label></li> - <li><label><input type="checkbox" name="beatles" value="P"> Paul</label></li> - <li><label><input type="checkbox" name="beatles" value="G"> George</label></li> - <li><label><input type="checkbox" name="beatles" value="R"> Ringo</label></li> - </ul>""" - )) + self.check_html(self.widget(choices=(('', 'Unknown'),) + self.beatles), 'beatles', None, html=""" + <div> + <div><label><input type="checkbox" name="beatles" value=""> Unknown</label></div> + <div><label><input type="checkbox" name="beatles" value="J"> John</label></div> + <div><label><input type="checkbox" name="beatles" value="P"> Paul</label></div> + <div><label><input type="checkbox" name="beatles" value="G"> George</label></div> + <div><label><input type="checkbox" name="beatles" value="R"> Ringo</label></div> + </div> + """) def test_nested_choices(self): nested_choices = ( @@ -52,31 +52,23 @@ class CheckboxSelectMultipleTest(WidgetTest): ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))), ) html = """ - <ul id="media"> - <li> - <label for="media_0"><input id="media_0" name="nestchoice" type="checkbox" value="unknown"> Unknown</label> - </li> - <li>Audio<ul id="media_1"> - <li> - <label for="media_1_0"> - <input checked id="media_1_0" name="nestchoice" type="checkbox" value="vinyl"> Vinyl - </label> - </li> - <li> - <label for="media_1_1"><input id="media_1_1" name="nestchoice" type="checkbox" value="cd"> CD</label> - </li> - </ul></li> - <li>Video<ul id="media_2"> - <li> - <label for="media_2_0"><input id="media_2_0" name="nestchoice" type="checkbox" value="vhs"> VHS</label> - </li> - <li> - <label for="media_2_1"> - <input checked id="media_2_1" name="nestchoice" type="checkbox" value="dvd"> DVD - </label> - </li> - </ul></li> - </ul> + <div id="media"> + <div> <label for="media_0"> + <input type="checkbox" name="nestchoice" value="unknown" id="media_0"> Unknown</label></div> + <div> + <label>Audio</label> + <div> <label for="media_1_0"> + <input checked type="checkbox" name="nestchoice" value="vinyl" id="media_1_0"> Vinyl</label></div> + <div> <label for="media_1_1"> + <input type="checkbox" name="nestchoice" value="cd" id="media_1_1"> CD</label></div> + </div><div> + <label>Video</label> + <div> <label for="media_2_0"> + <input type="checkbox" name="nestchoice" value="vhs" id="media_2_0"> VHS</label></div> + <div> <label for="media_2_1"> + <input type="checkbox" name="nestchoice" value="dvd" id="media_2_1" checked> DVD</label></div> + </div> + </div> """ self.check_html( self.widget(choices=nested_choices), 'nestchoice', ('vinyl', 'dvd'), @@ -90,31 +82,18 @@ class CheckboxSelectMultipleTest(WidgetTest): ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))), ) html = """ - <ul> - <li> - <label><input name="nestchoice" type="checkbox" value="unknown"> Unknown</label> - </li> - <li>Audio<ul> - <li> - <label> - <input checked name="nestchoice" type="checkbox" value="vinyl"> Vinyl - </label> - </li> - <li> - <label><input name="nestchoice" type="checkbox" value="cd"> CD</label> - </li> - </ul></li> - <li>Video<ul> - <li> - <label><input name="nestchoice" type="checkbox" value="vhs"> VHS</label> - </li> - <li> - <label> - <input checked name="nestchoice" type="checkbox" value="dvd"> DVD - </label> - </li> - </ul></li> - </ul> + <div> + <div> <label><input type="checkbox" name="nestchoice" value="unknown"> Unknown</label></div> + <div> + <label>Audio</label> + <div> <label><input checked type="checkbox" name="nestchoice" value="vinyl"> Vinyl</label></div> + <div> <label><input type="checkbox" name="nestchoice" value="cd"> CD</label></div> + </div><div> + <label>Video</label> + <div> <label><input type="checkbox" name="nestchoice" value="vhs"> VHS</label></div> + <div> <label><input type="checkbox" name="nestchoice" value="dvd"checked> DVD</label></div> + </div> + </div> """ self.check_html(self.widget(choices=nested_choices), 'nestchoice', ('vinyl', 'dvd'), html=html) @@ -124,15 +103,15 @@ class CheckboxSelectMultipleTest(WidgetTest): """ choices = [('a', 'A'), ('b', 'B'), ('c', 'C')] html = """ - <ul id="abc"> - <li> + <div id="abc"> + <div> <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0"> A</label> - </li> - <li><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1"> B</label></li> - <li> + </div> + <div><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1"> B</label></div> + <div> <label for="abc_2"><input checked type="checkbox" name="letters" value="c" id="abc_2"> C</label> - </li> - </ul> + </div> + </div> """ self.check_html(self.widget(choices=choices), 'letters', ['a', 'c'], attrs={'id': 'abc'}, html=html) @@ -142,15 +121,15 @@ class CheckboxSelectMultipleTest(WidgetTest): """ widget = CheckboxSelectMultiple(attrs={'id': 'abc'}, choices=[('a', 'A'), ('b', 'B'), ('c', 'C')]) html = """ - <ul id="abc"> - <li> + <div id="abc"> + <div> <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0"> A</label> - </li> - <li><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1"> B</label></li> - <li> + </div> + <div><label for="abc_1"><input type="checkbox" name="letters" value="b" id="abc_1"> B</label></div> + <div> <label for="abc_2"><input checked type="checkbox" name="letters" value="c" id="abc_2"> C</label> - </li> - </ul> + </div> + </div> """ self.check_html(widget, 'letters', ['a', 'c'], html=html) @@ -162,11 +141,11 @@ class CheckboxSelectMultipleTest(WidgetTest): (1000000, 'One million'), ] html = """ - <ul> - <li><label><input type="checkbox" name="numbers" value="1"> One</label></li> - <li><label><input type="checkbox" name="numbers" value="1000"> One thousand</label></li> - <li><label><input type="checkbox" name="numbers" value="1000000"> One million</label></li> - </ul> + <div> + <div><label><input type="checkbox" name="numbers" value="1"> One</label></div> + <div><label><input type="checkbox" name="numbers" value="1000"> One thousand</label></div> + <div><label><input type="checkbox" name="numbers" value="1000000"> One million</label></div> + </div> """ self.check_html(self.widget(choices=choices), 'numbers', None, html=html) @@ -175,10 +154,10 @@ class CheckboxSelectMultipleTest(WidgetTest): (datetime.time(12, 0), 'noon'), ] html = """ - <ul> - <li><label><input type="checkbox" name="times" value="00:00:00"> midnight</label></li> - <li><label><input type="checkbox" name="times" value="12:00:00"> noon</label></li> - </ul> + <div> + <div><label><input type="checkbox" name="times" value="00:00:00"> midnight</label></div> + <div><label><input type="checkbox" name="times" value="12:00:00"> noon</label></div> + </div> """ self.check_html(self.widget(choices=choices), 'times', None, html=html) diff --git a/tests/forms_tests/widget_tests/test_radioselect.py b/tests/forms_tests/widget_tests/test_radioselect.py index 0f85563a58..41f771e940 100644 --- a/tests/forms_tests/widget_tests/test_radioselect.py +++ b/tests/forms_tests/widget_tests/test_radioselect.py @@ -11,15 +11,15 @@ class RadioSelectTest(WidgetTest): def test_render(self): choices = (('', '------'),) + self.beatles - self.check_html(self.widget(choices=choices), 'beatle', 'J', html=( - """<ul> - <li><label><input type="radio" name="beatle" value=""> ------</label></li> - <li><label><input checked type="radio" name="beatle" value="J"> John</label></li> - <li><label><input type="radio" name="beatle" value="P"> Paul</label></li> - <li><label><input type="radio" name="beatle" value="G"> George</label></li> - <li><label><input type="radio" name="beatle" value="R"> Ringo</label></li> - </ul>""" - )) + self.check_html(self.widget(choices=choices), 'beatle', 'J', html=""" + <div> + <div><label><input type="radio" name="beatle" value=""> ------</label></div> + <div><label><input checked type="radio" name="beatle" value="J"> John</label></div> + <div><label><input type="radio" name="beatle" value="P"> Paul</label></div> + <div><label><input type="radio" name="beatle" value="G"> George</label></div> + <div><label><input type="radio" name="beatle" value="R"> Ringo</label></div> + </div> + """) def test_nested_choices(self): nested_choices = ( @@ -28,25 +28,23 @@ class RadioSelectTest(WidgetTest): ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))), ) html = """ - <ul id="media"> - <li> - <label for="media_0"><input id="media_0" name="nestchoice" type="radio" value="unknown"> Unknown</label> - </li> - <li>Audio<ul id="media_1"> - <li> - <label for="media_1_0"><input id="media_1_0" name="nestchoice" type="radio" value="vinyl"> Vinyl</label> - </li> - <li><label for="media_1_1"><input id="media_1_1" name="nestchoice" type="radio" value="cd"> CD</label></li> - </ul></li> - <li>Video<ul id="media_2"> - <li><label for="media_2_0"><input id="media_2_0" name="nestchoice" type="radio" value="vhs"> VHS</label></li> - <li> - <label for="media_2_1"> - <input checked id="media_2_1" name="nestchoice" type="radio" value="dvd"> DVD - </label> - </li> - </ul></li> - </ul> + <div id="media"> + <div> + <label for="media_0"><input type="radio" name="nestchoice" value="unknown" id="media_0"> Unknown</label></div> + <div> + <label>Audio</label> + <div> + <label for="media_1_0"><input type="radio" name="nestchoice" value="vinyl" id="media_1_0"> Vinyl</label></div> + <div> <label for="media_1_1"><input type="radio" name="nestchoice" value="cd" id="media_1_1"> CD</label></div> + </div><div> + <label>Video</label> + <div> + <label for="media_2_0"><input type="radio" name="nestchoice" value="vhs" id="media_2_0"> VHS</label></div> + <div> + <label for="media_2_1"><input type="radio" name="nestchoice" value="dvd" id="media_2_1" checked> DVD</label> + </div> + </div> + </div> """ self.check_html( self.widget(choices=nested_choices), 'nestchoice', 'dvd', @@ -60,14 +58,14 @@ class RadioSelectTest(WidgetTest): """ widget = RadioSelect(attrs={'id': 'foo'}, choices=self.beatles) html = """ - <ul id="foo"> - <li> + <div id="foo"> + <div> <label for="foo_0"><input checked type="radio" id="foo_0" value="J" name="beatle"> John</label> - </li> - <li><label for="foo_1"><input type="radio" id="foo_1" value="P" name="beatle"> Paul</label></li> - <li><label for="foo_2"><input type="radio" id="foo_2" value="G" name="beatle"> George</label></li> - <li><label for="foo_3"><input type="radio" id="foo_3" value="R" name="beatle"> Ringo</label></li> - </ul> + </div> + <div><label for="foo_1"><input type="radio" id="foo_1" value="P" name="beatle"> Paul</label></div> + <div><label for="foo_2"><input type="radio" id="foo_2" value="G" name="beatle"> George</label></div> + <div><label for="foo_3"><input type="radio" id="foo_3" value="R" name="beatle"> Ringo</label></div> + </div> """ self.check_html(widget, 'beatle', 'J', html=html) @@ -77,29 +75,29 @@ class RadioSelectTest(WidgetTest): inputs. """ html = """ - <ul id="bar"> - <li> + <div id="bar"> + <div> <label for="bar_0"><input checked type="radio" id="bar_0" value="J" name="beatle"> John</label> - </li> - <li><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle"> Paul</label></li> - <li><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle"> George</label></li> - <li><label for="bar_3"><input type="radio" id="bar_3" value="R" name="beatle"> Ringo</label></li> - </ul> + </div> + <div><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle"> Paul</label></div> + <div><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle"> George</label></div> + <div><label for="bar_3"><input type="radio" id="bar_3" value="R" name="beatle"> Ringo</label></div> + </div> """ self.check_html(self.widget(choices=self.beatles), 'beatle', 'J', attrs={'id': 'bar'}, html=html) def test_class_attrs(self): """ - The <ul> in the multiple_input.html widget template include the class + The <div> in the multiple_input.html widget template include the class attribute. """ html = """ - <ul class="bar"> - <li><label><input checked type="radio" class="bar" value="J" name="beatle"> John</label></li> - <li><label><input type="radio" class="bar" value="P" name="beatle"> Paul</label></li> - <li><label><input type="radio" class="bar" value="G" name="beatle"> George</label></li> - <li><label><input type="radio" class="bar" value="R" name="beatle"> Ringo</label></li> - </ul> + <div class="bar"> + <div><label><input checked type="radio" class="bar" value="J" name="beatle"> John</label></div> + <div><label><input type="radio" class="bar" value="P" name="beatle"> Paul</label></div> + <div><label><input type="radio" class="bar" value="G" name="beatle"> George</label></div> + <div><label><input type="radio" class="bar" value="R" name="beatle"> Ringo</label></div> + </div> """ self.check_html(self.widget(choices=self.beatles), 'beatle', 'J', attrs={'class': 'bar'}, html=html) @@ -111,11 +109,11 @@ class RadioSelectTest(WidgetTest): (1000000, 'One million'), ] html = """ - <ul> - <li><label><input type="radio" name="number" value="1"> One</label></li> - <li><label><input type="radio" name="number" value="1000"> One thousand</label></li> - <li><label><input type="radio" name="number" value="1000000"> One million</label></li> - </ul> + <div> + <div><label><input type="radio" name="number" value="1"> One</label></div> + <div><label><input type="radio" name="number" value="1000"> One thousand</label></div> + <div><label><input type="radio" name="number" value="1000000"> One million</label></div> + </div> """ self.check_html(self.widget(choices=choices), 'number', None, html=html) @@ -124,22 +122,22 @@ class RadioSelectTest(WidgetTest): (datetime.time(12, 0), 'noon'), ] html = """ - <ul> - <li><label><input type="radio" name="time" value="00:00:00"> midnight</label></li> - <li><label><input type="radio" name="time" value="12:00:00"> noon</label></li> - </ul> + <div> + <div><label><input type="radio" name="time" value="00:00:00"> midnight</label></div> + <div><label><input type="radio" name="time" value="12:00:00"> noon</label></div> + </div> """ self.check_html(self.widget(choices=choices), 'time', None, html=html) def test_render_as_subwidget(self): """A RadioSelect as a subwidget of MultiWidget.""" choices = (('', '------'),) + self.beatles - self.check_html(MultiWidget([self.widget(choices=choices)]), 'beatle', ['J'], html=( - """<ul> - <li><label><input type="radio" name="beatle_0" value=""> ------</label></li> - <li><label><input checked type="radio" name="beatle_0" value="J"> John</label></li> - <li><label><input type="radio" name="beatle_0" value="P"> Paul</label></li> - <li><label><input type="radio" name="beatle_0" value="G"> George</label></li> - <li><label><input type="radio" name="beatle_0" value="R"> Ringo</label></li> - </ul>""" - )) + self.check_html(MultiWidget([self.widget(choices=choices)]), 'beatle', ['J'], html=""" + <div> + <div><label><input type="radio" name="beatle_0" value=""> ------</label></div> + <div><label><input checked type="radio" name="beatle_0" value="J"> John</label></div> + <div><label><input type="radio" name="beatle_0" value="P"> Paul</label></div> + <div><label><input type="radio" name="beatle_0" value="G"> George</label></div> + <div><label><input type="radio" name="beatle_0" value="R"> Ringo</label></div> + </div> + """) diff --git a/tests/model_forms/test_modelchoicefield.py b/tests/model_forms/test_modelchoicefield.py index 8f41ce9c40..2a0c05d803 100644 --- a/tests/model_forms/test_modelchoicefield.py +++ b/tests/model_forms/test_modelchoicefield.py @@ -294,14 +294,14 @@ class ModelChoiceFieldTests(TestCase): field = CustomModelMultipleChoiceField(Category.objects.all()) self.assertHTMLEqual( field.widget.render('name', []), ( - '<ul>' - '<li><label><input type="checkbox" name="name" value="%d" ' - 'data-slug="entertainment">Entertainment</label></li>' - '<li><label><input type="checkbox" name="name" value="%d" ' - 'data-slug="test">A test</label></li>' - '<li><label><input type="checkbox" name="name" value="%d" ' - 'data-slug="third-test">Third</label></li>' - '</ul>' + '<div>' + '<div><label><input type="checkbox" name="name" value="%d" ' + 'data-slug="entertainment">Entertainment</label></div>' + '<div><label><input type="checkbox" name="name" value="%d" ' + 'data-slug="test">A test</label></div>' + '<div><label><input type="checkbox" name="name" value="%d" ' + 'data-slug="third-test">Third</label></div>' + '</div>' ) % (self.c1.pk, self.c2.pk, self.c3.pk), ) @@ -334,11 +334,11 @@ class ModelChoiceFieldTests(TestCase): field = CustomModelMultipleChoiceField(Category.objects.all()) self.assertHTMLEqual( field.widget.render('name', []), - '''<ul> -<li><label><input type="checkbox" name="name" value="%d" data-slug="entertainment">Entertainment</label></li> -<li><label><input type="checkbox" name="name" value="%d" data-slug="test">A test</label></li> -<li><label><input type="checkbox" name="name" value="%d" data-slug="third-test">Third</label></li> -</ul>''' % (self.c1.pk, self.c2.pk, self.c3.pk), + """<div> +<div><label><input type="checkbox" name="name" value="%d" data-slug="entertainment">Entertainment</label></div> +<div><label><input type="checkbox" name="name" value="%d" data-slug="test">A test</label></div> +<div><label><input type="checkbox" name="name" value="%d" data-slug="third-test">Third</label></div> +</div>""" % (self.c1.pk, self.c2.pk, self.c3.pk), ) def test_choices_not_fetched_when_not_rendering(self): |
