2
0
Эх сурвалжийг харах

Fixed #28157 -- Fixed choice ordering in form fields with grouped and non-grouped options.

Regression in b52c73008a9d67e9ddbb841872dc15cdd3d6ee01.
Tim Graham 8 жил өмнө
parent
commit
d302e2c09c

+ 6 - 8
django/forms/widgets.py

@@ -547,25 +547,23 @@ class ChoiceWidget(Widget):
 
     def optgroups(self, name, value, attrs=None):
         """Return a list of optgroups for this widget."""
-        default = (None, [], 0)
-        groups = [default]
+        groups = []
         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:
                 option_value = ''
 
+            subgroup = []
             if isinstance(option_label, (list, tuple)):
-                index = groups[-1][2] + 1
+                group_name = option_value
                 subindex = 0
-                subgroup = []
-                groups.append((option_value, subgroup, index))
                 choices = option_label
             else:
-                index = len(default[1])
-                subgroup = default[1]
+                group_name = None
                 subindex = None
                 choices = [(option_value, option_label)]
+            groups.append((group_name, subgroup, index))
 
             for subvalue, sublabel in choices:
                 selected = (

+ 3 - 0
docs/releases/1.11.1.txt

@@ -78,3 +78,6 @@ Bugfixes
 
 * Prevented migrations from dropping database indexes from ``Meta.indexes``
   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`).

+ 67 - 29
tests/forms_tests/widget_tests/test_select.py

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