Fixed #32460 -- Allowed "label"/"do_not_call_in_templates" members in model choice enums.
This commit is contained in:
parent
41e39c41c9
commit
a96c730431
|
@ -1,4 +1,5 @@
|
|||
import enum
|
||||
from types import DynamicClassAttribute
|
||||
|
||||
from django.utils.functional import Promise
|
||||
|
||||
|
@ -26,12 +27,8 @@ class ChoicesMeta(enum.EnumMeta):
|
|||
# assignment in enum's classdict.
|
||||
dict.__setitem__(classdict, key, value)
|
||||
cls = super().__new__(metacls, classname, bases, classdict, **kwds)
|
||||
cls._value2label_map_ = dict(zip(cls._value2member_map_, labels))
|
||||
# Add a label property to instances of enum which uses the enum member
|
||||
# that is passed in as "self" as the value to use when looking up the
|
||||
# label in the choices.
|
||||
cls.label = property(lambda self: cls._value2label_map_.get(self.value))
|
||||
cls.do_not_call_in_templates = True
|
||||
for member, label in zip(cls.__members__.values(), labels):
|
||||
member._label_ = label
|
||||
return enum.unique(cls)
|
||||
|
||||
def __contains__(cls, member):
|
||||
|
@ -62,6 +59,14 @@ class ChoicesMeta(enum.EnumMeta):
|
|||
class Choices(enum.Enum, metaclass=ChoicesMeta):
|
||||
"""Class for creating enumerated choices."""
|
||||
|
||||
@DynamicClassAttribute
|
||||
def label(self):
|
||||
return self._label_
|
||||
|
||||
@property
|
||||
def do_not_call_in_templates(self):
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Use value when cast to str, so that Choices set as model instance
|
||||
|
|
|
@ -159,6 +159,26 @@ class ChoicesTests(SimpleTestCase):
|
|||
with self.assertRaises(AttributeError):
|
||||
models.TextChoices('Properties', 'choices labels names values')
|
||||
|
||||
def test_label_member(self):
|
||||
# label can be used as a member.
|
||||
Stationery = models.TextChoices('Stationery', 'label stamp sticker')
|
||||
self.assertEqual(Stationery.label.label, 'Label')
|
||||
self.assertEqual(Stationery.label.value, 'label')
|
||||
self.assertEqual(Stationery.label.name, 'label')
|
||||
|
||||
def test_do_not_call_in_templates_member(self):
|
||||
# do_not_call_in_templates is not implicitly treated as a member.
|
||||
Special = models.IntegerChoices('Special', 'do_not_call_in_templates')
|
||||
self.assertEqual(
|
||||
Special.do_not_call_in_templates.label,
|
||||
'Do Not Call In Templates',
|
||||
)
|
||||
self.assertEqual(Special.do_not_call_in_templates.value, 1)
|
||||
self.assertEqual(
|
||||
Special.do_not_call_in_templates.name,
|
||||
'do_not_call_in_templates',
|
||||
)
|
||||
|
||||
|
||||
class Separator(bytes, models.Choices):
|
||||
FS = b'\x1c', 'File Separator'
|
||||
|
|
Loading…
Reference in New Issue