From ad37867bc64907c203396941aac3134d805d440c Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 30 Apr 2020 22:40:01 +0100 Subject: [PATCH] Support optgroups in FilteredSelect --- wagtail/admin/tests/test_widgets.py | 34 ++++++++++++++++++++++++ wagtail/admin/widgets/filtered_select.py | 13 +++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/wagtail/admin/tests/test_widgets.py b/wagtail/admin/tests/test_widgets.py index 5cc66ce96d..e5cb6749be 100644 --- a/wagtail/admin/tests/test_widgets.py +++ b/wagtail/admin/tests/test_widgets.py @@ -322,3 +322,37 @@ class TestFilteredSelect(TestCase): ''') + + def test_optgroups(self): + widget = widgets.FilteredSelect(choices=[ + (None, '----'), + ('Big countries', [ + ('FR', 'France', ['EU']), + ('JP', 'Japan', ['AS']), + ('RU', 'Russia', ['AS', 'EU']), + ('MOON', 'The moon'), + ]), + ('Small countries', [ + ('AZ', 'Azerbaijan', ['AS']), + ('LI', 'Liechtenstein', ['EU']), + ]), + ('SK', 'Slovakia', ['EU']) + ], filter_field='id_continent') + + html = widget.render('country', 'JP') + self.assertHTMLEqual(html, ''' + + ''') diff --git a/wagtail/admin/widgets/filtered_select.py b/wagtail/admin/widgets/filtered_select.py index 10a77557ee..bf57726889 100644 --- a/wagtail/admin/widgets/filtered_select.py +++ b/wagtail/admin/widgets/filtered_select.py @@ -53,16 +53,25 @@ class FilteredSelect(forms.Select): subgroup = [] if isinstance(option_label, (list, tuple)): + # this is an optgroup - we will iterate over the list in the second item of + # the tuple (which has been assigned to option_label) group_name = option_value subindex = 0 choices = option_label else: + # this is a top-level choice; put it in its own group with no name group_name = None subindex = None - choices = [(option_value, option_label)] + choices = [(option_value, option_label, filter_value)] groups.append((group_name, subgroup, index)) - for subvalue, sublabel in choices: + for choice in choices: + try: + (subvalue, sublabel, filter_value) = choice + except ValueError: + (subvalue, sublabel) = choice + filter_value = None + selected = ( str(subvalue) in value and (not has_selected or self.allow_multiple_selected)