django adding extra data to IntegerChoices

74 Views Asked by At

I need to add extra data to enum Class IntegerChoice in django. I have carefully read the answer here How to add extra data to TextChoices? but it does not seem to work. the definition of my enum type is :

class FabricType (models.IntegerChoices):
"""an enumeration class with type, subclass and key words added
first item is the code,
second is translated verbose name,
third is choice specific help,
third is Group
fourth is a list of keywords
anychange in the number will require migration but adding new keywords will  not
"""

CASTON = (1, _('Caston'), _('Basic'), [])
JERSEY = (2, _('Jersey'), _('Basic'), [])
TUBULAR = (3, _('Tubular'), _('Basic'), [])

def __new__(cls, value, label, group, keywords, ):
    obj = int.__new__(cls, value)
    obj._value_ = value
    obj.group = group
    obj.keywords = keywords
    obj.help = help
    return obj
def help_dict(cls):
    """help_dict for the FabricType"""
    help_dict = {'CASTON': _('the first few rows of a knit'),
                 'JERSEY': _('help_text'),
                 'TUBULAR': _('help text')
    return help_dict

I have declared the EnumMixin as follows :

class EnumMixin:
''' an Enum which Converts a DB value back to its Choices value'''

def __init__(self, *args, enum=models.Choices, **kwargs):
    self.__enum = enum
    self.help_dict = kwargs.get('help_dict', None)
    kwargs.pop('help_dict', None)
    # it sets choices for you using the enum
    super().__init__(*args, **kwargs)

def deconstruct(self):
    'Get constructor args to reconstruct this field with later'
    name, path, args, kwargs = super().deconstruct()
    kwargs['enum'] = self.__enum
    kwargs['help_dict'] = self.help_dict
    try:
        del kwargs['choices']
    except KeyError:
        pass
    return name, path, args, kwargs

def from_db_value(self, value, expression, connection):
    # Convert from db value
    return self.__to_enum(value)

def to_python(self, value):
    'Called by deserialization and during clean() method used in forms'
    return self.__to_enum(value)

def __to_enum(self, value):
    if value is None:
        return None
    return self.__enum(value)

def help_dict(self):
    return

my field is declared as follows:

class FabricTypeField(EnumMixin, models.SmallIntegerField):

    pass

When I create an object in the database with value 2, I get the following error : builtins.ValueError : 2 is not a valid Choices.

in the EnumMixin class __to_enum(self, value) is called but self.__enum(value) ends up in the Python EnumMeta(type) and not in my enum class.

1

There are 1 best solutions below

0
piscvau On

The error came from the declaration of the field in the model where I forgot to mention the type of the enum

class Fabric(models.Model) :
    fabric_type = FabricTypeField(
         **enum=FabricType,**
         verbose_name=_('fabric_type'),
         )