123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- import datetime
- from django.forms import ChoiceField, Form, MultiWidget, Select, TextInput
- from django.test import override_settings
- from django.utils.safestring import mark_safe
- from .test_choicewidget import ChoiceWidgetTest
- class SelectTest(ChoiceWidgetTest):
- widget = Select
- def test_render(self):
- self.check_html(
- self.widget(choices=self.beatles),
- "beatle",
- "J",
- html=(
- """<select name="beatle">
- <option value="J" selected>John</option>
- <option value="P">Paul</option>
- <option value="G">George</option>
- <option value="R">Ringo</option>
- </select>"""
- ),
- )
- def test_render_none(self):
- """
- If the value is None, none of the options are selected.
- """
- self.check_html(
- self.widget(choices=self.beatles),
- "beatle",
- None,
- html=(
- """<select name="beatle">
- <option value="J">John</option>
- <option value="P">Paul</option>
- <option value="G">George</option>
- <option value="R">Ringo</option>
- </select>"""
- ),
- )
- def test_render_label_value(self):
- """
- If the value corresponds to a label (but not to an option value), none
- of the options are selected.
- """
- self.check_html(
- self.widget(choices=self.beatles),
- "beatle",
- "John",
- html=(
- """<select name="beatle">
- <option value="J">John</option>
- <option value="P">Paul</option>
- <option value="G">George</option>
- <option value="R">Ringo</option>
- </select>"""
- ),
- )
- def test_render_selected(self):
- """
- Only one option can be selected (#8103).
- """
- choices = [("0", "0"), ("1", "1"), ("2", "2"), ("3", "3"), ("0", "extra")]
- self.check_html(
- self.widget(choices=choices),
- "choices",
- "0",
- html=(
- """<select name="choices">
- <option value="0" selected>0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- <option value="3">3</option>
- <option value="0">extra</option>
- </select>"""
- ),
- )
- def test_constructor_attrs(self):
- """
- Select options shouldn't inherit the parent widget attrs.
- """
- widget = Select(
- attrs={"class": "super", "id": "super"},
- choices=[(1, 1), (2, 2), (3, 3)],
- )
- self.check_html(
- widget,
- "num",
- 2,
- html=(
- """<select name="num" class="super" id="super">
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- </select>"""
- ),
- )
- def test_compare_to_str(self):
- """
- The value is compared to its str().
- """
- self.check_html(
- self.widget(choices=[("1", "1"), ("2", "2"), ("3", "3")]),
- "num",
- 2,
- html=(
- """<select name="num">
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- </select>"""
- ),
- )
- self.check_html(
- self.widget(choices=[(1, 1), (2, 2), (3, 3)]),
- "num",
- "2",
- html=(
- """<select name="num">
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- </select>"""
- ),
- )
- self.check_html(
- self.widget(choices=[(1, 1), (2, 2), (3, 3)]),
- "num",
- 2,
- html=(
- """<select name="num">
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- </select>"""
- ),
- )
- def test_choices_constructor(self):
- widget = Select(choices=[(1, 1), (2, 2), (3, 3)])
- self.check_html(
- widget,
- "num",
- 2,
- html=(
- """<select name="num">
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- </select>"""
- ),
- )
- def test_choices_constructor_generator(self):
- """
- If choices is passed to the constructor and is a generator, it can be
- iterated over multiple times without getting consumed.
- """
- def get_choices():
- for i in range(5):
- yield (i, i)
- widget = Select(choices=get_choices())
- self.check_html(
- widget,
- "num",
- 2,
- html=(
- """<select name="num">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2" selected>2</option>
- <option value="3">3</option>
- <option value="4">4</option>
- </select>"""
- ),
- )
- self.check_html(
- widget,
- "num",
- 3,
- html=(
- """<select name="num">
- <option value="0">0</option>
- <option value="1">1</option>
- <option value="2">2</option>
- <option value="3" selected>3</option>
- <option value="4">4</option>
- </select>"""
- ),
- )
- def test_choices_escaping(self):
- choices = (("bad", "you & me"), ("good", mark_safe("you > me")))
- self.check_html(
- self.widget(choices=choices),
- "escape",
- None,
- html=(
- """<select name="escape">
- <option value="bad">you & me</option>
- <option value="good">you > me</option>
- </select>"""
- ),
- )
- def test_choices_unicode(self):
- self.check_html(
- self.widget(choices=[("ŠĐĆŽćžšđ", "ŠĐabcĆŽćžšđ"), ("ćžšđ", "abcćžšđ")]),
- "email",
- "ŠĐĆŽćžšđ",
- html=(
- """
- <select name="email">
- <option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111"
- selected>
- \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111
- </option>
- <option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111
- </option>
- </select>
- """
- ),
- )
- def test_choices_optgroup(self):
- """
- Choices can be nested one level in order to create HTML optgroups.
- """
- self.check_html(
- self.nested_widget,
- "nestchoice",
- None,
- html=(
- """<select name="nestchoice">
- <option value="outer1">Outer 1</option>
- <optgroup label="Group "1"">
- <option value="inner1">Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
- def test_choices_select_outer(self):
- self.check_html(
- self.nested_widget,
- "nestchoice",
- "outer1",
- html=(
- """<select name="nestchoice">
- <option value="outer1" selected>Outer 1</option>
- <optgroup label="Group "1"">
- <option value="inner1">Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
- def test_choices_select_inner(self):
- self.check_html(
- self.nested_widget,
- "nestchoice",
- "inner1",
- html=(
- """<select name="nestchoice">
- <option value="outer1">Outer 1</option>
- <optgroup label="Group "1"">
- <option value="inner1" selected>Inner 1</option>
- <option value="inner2">Inner 2</option>
- </optgroup>
- </select>"""
- ),
- )
- @override_settings(USE_THOUSAND_SEPARATOR=True)
- def test_doesnt_localize_option_value(self):
- choices = [
- (1, "One"),
- (1000, "One thousand"),
- (1000000, "One million"),
- ]
- html = """
- <select name="number">
- <option value="1">One</option>
- <option value="1000">One thousand</option>
- <option value="1000000">One million</option>
- </select>
- """
- self.check_html(self.widget(choices=choices), "number", None, html=html)
- choices = [
- (datetime.time(0, 0), "midnight"),
- (datetime.time(12, 0), "noon"),
- ]
- html = """
- <select name="time">
- <option value="00:00:00">midnight</option>
- <option value="12:00:00">noon</option>
- </select>
- """
- self.check_html(self.widget(choices=choices), "time", None, html=html)
- def test_optgroups(self):
- choices = [
- (
- "Audio",
- [
- ("vinyl", "Vinyl"),
- ("cd", "CD"),
- ],
- ),
- (
- "Video",
- [
- ("vhs", "VHS Tape"),
- ("dvd", "DVD"),
- ],
- ),
- ("unknown", "Unknown"),
- ]
- groups = list(
- self.widget(choices=choices).optgroups(
- "name",
- ["vhs"],
- attrs={"class": "super"},
- )
- )
- audio, video, unknown = groups
- label, options, index = audio
- self.assertEqual(label, "Audio")
- self.assertEqual(
- options,
- [
- {
- "value": "vinyl",
- "type": "select",
- "attrs": {},
- "index": "0_0",
- "label": "Vinyl",
- "template_name": "django/forms/widgets/select_option.html",
- "name": "name",
- "selected": False,
- "wrap_label": True,
- },
- {
- "value": "cd",
- "type": "select",
- "attrs": {},
- "index": "0_1",
- "label": "CD",
- "template_name": "django/forms/widgets/select_option.html",
- "name": "name",
- "selected": False,
- "wrap_label": True,
- },
- ],
- )
- self.assertEqual(index, 0)
- label, options, index = video
- self.assertEqual(label, "Video")
- self.assertEqual(
- options,
- [
- {
- "value": "vhs",
- "template_name": "django/forms/widgets/select_option.html",
- "label": "VHS Tape",
- "attrs": {"selected": True},
- "index": "1_0",
- "name": "name",
- "selected": True,
- "type": "select",
- "wrap_label": True,
- },
- {
- "value": "dvd",
- "template_name": "django/forms/widgets/select_option.html",
- "label": "DVD",
- "attrs": {},
- "index": "1_1",
- "name": "name",
- "selected": False,
- "type": "select",
- "wrap_label": True,
- },
- ],
- )
- self.assertEqual(index, 1)
- label, options, index = unknown
- self.assertIsNone(label)
- self.assertEqual(
- options,
- [
- {
- "value": "unknown",
- "selected": False,
- "template_name": "django/forms/widgets/select_option.html",
- "label": "Unknown",
- "attrs": {},
- "index": "2",
- "name": "name",
- "type": "select",
- "wrap_label": True,
- }
- ],
- )
- self.assertEqual(index, 2)
- def test_doesnt_render_required_when_impossible_to_select_empty_field(self):
- widget = self.widget(choices=[("J", "John"), ("P", "Paul")])
- self.assertIs(widget.use_required_attribute(initial=None), False)
- def test_doesnt_render_required_when_no_choices_are_available(self):
- widget = self.widget(choices=[])
- self.assertIs(widget.use_required_attribute(initial=None), False)
- def test_render_as_subwidget(self):
- """A RadioSelect as a subwidget of MultiWidget."""
- choices = (("", "------"),) + self.beatles
- self.check_html(
- MultiWidget([self.widget(choices=choices), TextInput()]),
- "beatle",
- ["J", "Some text"],
- html=(
- """
- <select name="beatle_0">
- <option value="">------</option>
- <option value="J" selected>John</option>
- <option value="P">Paul</option>
- <option value="G">George</option>
- <option value="R">Ringo</option>
- </select>
- <input name="beatle_1" type="text" value="Some text">
- """
- ),
- )
- 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(),
- )
|