Refs #32338 -- Made RadioSelect/CheckboxSelectMultiple render in <div> tags.
This improves accessibility for screen reader users.
This commit is contained in:
parent
a5cb1ef6eb
commit
5942ab5eb1
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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>
|
||||
""")
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue