CHOICE_SETS values (IATA, ISO_3166, UN_LOCODE) are lists of (value, label) tuples, not dicts. The .values() call introduced by #21984 treated them as dicts, raising AttributeError: 'list' object has no attribute 'values' when full_clean() was invoked during choice set creation. Replace with a generator expression that extracts the first element from each tuple, matching the same pattern used elsewhere in the same model. Also covers the save() path when order_alphabetically=True but extra_choices is None (base-only choice set), preventing a TypeError when sorted() receives None.
This commit is contained in:
parent
3ee228f69a
commit
352860daf0
|
|
@ -972,7 +972,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, OwnerMixin, Chang
|
|||
extra_choice_values = set()
|
||||
|
||||
if self.base_choices:
|
||||
valid_choice_values.update(CHOICE_SETS.get(self.base_choices).values())
|
||||
valid_choice_values.update(value for value, _ in CHOICE_SETS.get(self.base_choices))
|
||||
|
||||
if self.extra_choices:
|
||||
for value, _label in self.extra_choices:
|
||||
|
|
@ -1031,7 +1031,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, OwnerMixin, Chang
|
|||
def save(self, *args, **kwargs):
|
||||
|
||||
# Sort choices if alphabetical ordering is enforced
|
||||
if self.order_alphabetically:
|
||||
if self.order_alphabetically and self.extra_choices:
|
||||
self.extra_choices = sorted(self.extra_choices, key=lambda x: x[0])
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -466,6 +466,15 @@ class CustomFieldTestCase(TestCase):
|
|||
|
||||
self.assertIn('choice_colors', cm.exception.message_dict)
|
||||
|
||||
@tag('regression')
|
||||
def test_choice_set_with_base_choices_validates_without_error(self):
|
||||
"""Regression test for #22325: base-only choice sets must validate."""
|
||||
for base in ('IATA', 'ISO_3166', 'UN_LOCODE'):
|
||||
with self.subTest(base=base):
|
||||
choice_set = CustomFieldChoiceSet(name=f'Test {base}', base_choices=base, order_alphabetically=True)
|
||||
choice_set.full_clean() # must not raise
|
||||
choice_set.save() # must not raise (extra_choices is None)
|
||||
|
||||
def test_remove_selected_choice(self):
|
||||
"""
|
||||
Removing a ChoiceSet choice that is referenced by an object should raise
|
||||
|
|
|
|||
Loading…
Reference in New Issue