[1.11.x] Fixed #28157 -- Fixed choice ordering in form fields with grouped and non-grouped options.

Regression in b52c73008a.

Backport of d302e2c09c from master
This commit is contained in:
Tim Graham 2017-05-03 07:21:44 -04:00
parent 72a93da1b6
commit 0615601498
3 changed files with 76 additions and 37 deletions

View File

@ -567,25 +567,23 @@ class ChoiceWidget(Widget):
def optgroups(self, name, value, attrs=None): def optgroups(self, name, value, attrs=None):
"""Return a list of optgroups for this widget.""" """Return a list of optgroups for this widget."""
default = (None, [], 0) groups = []
groups = [default]
has_selected = False has_selected = False
for option_value, option_label in chain(self.choices): for index, (option_value, option_label) in enumerate(chain(self.choices)):
if option_value is None: if option_value is None:
option_value = '' option_value = ''
subgroup = []
if isinstance(option_label, (list, tuple)): if isinstance(option_label, (list, tuple)):
index = groups[-1][2] + 1 group_name = option_value
subindex = 0 subindex = 0
subgroup = []
groups.append((option_value, subgroup, index))
choices = option_label choices = option_label
else: else:
index = len(default[1]) group_name = None
subgroup = default[1]
subindex = None subindex = None
choices = [(option_value, option_label)] choices = [(option_value, option_label)]
groups.append((group_name, subgroup, index))
for subvalue, sublabel in choices: for subvalue, sublabel in choices:
selected = ( selected = (

View File

@ -78,3 +78,6 @@ Bugfixes
* Prevented migrations from dropping database indexes from ``Meta.indexes`` * Prevented migrations from dropping database indexes from ``Meta.indexes``
when changing ``Field.db_index`` to ``False`` (:ticket:`28052`). when changing ``Field.db_index`` to ``False`` (:ticket:`28052`).
* Fixed a regression in choice ordering in form fields with grouped and
non-grouped options (:ticket:`28157`).

View File

@ -283,35 +283,73 @@ class SelectTest(WidgetTest):
groups = list(self.widget(choices=choices).optgroups( groups = list(self.widget(choices=choices).optgroups(
'name', ['vhs'], attrs={'class': 'super'}, 'name', ['vhs'], attrs={'class': 'super'},
)) ))
self.assertEqual(len(groups), 3) audio, video, unknown = groups
self.assertEqual(groups[0][0], None) label, options, index = audio
self.assertEqual(groups[0][2], 0) self.assertEqual(label, 'Audio')
self.assertEqual(len(groups[0][1]), 1) self.assertEqual(
options = groups[0][1] options,
self.assertEqual(options[0]['name'], 'name') [{
self.assertEqual(options[0]['value'], 'unknown') 'value': 'vinyl',
self.assertEqual(options[0]['label'], 'Unknown') 'type': 'select',
self.assertEqual(options[0]['index'], '0') 'attrs': {},
self.assertEqual(options[0]['selected'], False) 'index': '0_0',
self.assertEqual(groups[1][0], 'Audio') 'label': 'Vinyl',
self.assertEqual(groups[1][2], 1) 'template_name': 'django/forms/widgets/select_option.html',
self.assertEqual(len(groups[1][1]), 2) 'name': 'name',
options = groups[1][1] 'selected': False,
self.assertEqual(options[0]['name'], 'name') }, {
self.assertEqual(options[0]['value'], 'vinyl') 'value': 'cd',
self.assertEqual(options[0]['label'], 'Vinyl') 'type': 'select',
self.assertEqual(options[0]['index'], '1_0') 'attrs': {},
self.assertEqual(options[1]['index'], '1_1') 'index': '0_1',
self.assertEqual(groups[2][0], 'Video') 'label': 'CD',
self.assertEqual(groups[2][2], 2) 'template_name': 'django/forms/widgets/select_option.html',
self.assertEqual(len(groups[2][1]), 2) 'name': 'name',
options = groups[2][1] 'selected': False,
self.assertEqual(options[0]['name'], 'name') }]
self.assertEqual(options[0]['value'], 'vhs') )
self.assertEqual(options[0]['label'], 'VHS Tape') self.assertEqual(index, 0)
self.assertEqual(options[0]['index'], '2_0') label, options, index = video
self.assertEqual(options[0]['selected'], True) self.assertEqual(label, 'Video')
self.assertEqual(options[1]['index'], '2_1') 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',
}, {
'value': 'dvd',
'template_name': 'django/forms/widgets/select_option.html',
'label': 'DVD',
'attrs': {},
'index': '1_1',
'name': 'name',
'selected': False,
'type': 'select',
}]
)
self.assertEqual(index, 1)
label, options, index = unknown
self.assertEqual(label, None)
self.assertEqual(
options,
[{
'value': 'unknown',
'selected': False,
'template_name': 'django/forms/widgets/select_option.html',
'label': 'Unknown',
'attrs': {},
'index': '2',
'name': 'name',
'type': 'select',
}]
)
self.assertEqual(index, 2)
def test_deepcopy(self): def test_deepcopy(self):
""" """