I am trying to use the new Enum types in the latest Django version for the choice field. Specifically I am trying to store the various states of United States as follows:
class States(models.TextChoices):
ALABAMA = 'AL', 'Alabama'
ALASKA = 'AK', 'Alaska'
.....
.....
WISCONSIN = 'WI', 'Wisconsin'
WYOMING = 'WY', 'Wyoming'
class PersonalInfo(models.Model):
state = models.CharField(max_length=2, choices=States.choices, default=States.ALABAMA)
Works as expected. Now, I am also trying to make the max_length variable also a class attribute of the choice class to make the code more modular by doing the following:
class States(models.TextChoices):
ALABAMA = 'AL', 'Alabama'
ALASKA = 'AK', 'Alaska'
.....
.....
WISCONSIN = 'WI', 'Wisconsin'
WYOMING = 'WY', 'Wyoming'
MAX_LENGTH = 2
class PersonalInfo(models.Model):
state = models.CharField(max_length=States.MAX_LENGTH, choices=States.choices, default=States.ALABAMA)
This gives me an error as follows:
if self.max_length is not None and choice_max_length > self.max_length:
TypeError: '>' not supported between instances of 'int' and 'States'
I understand that Django also provides an alternative IntegerChoices for integer but how do I use both text and integer choices together.
TextChoices
has to contain string values and the way these work is that they enumerate what you define in the class. So you've got a mixture of types which won't work because it'll try to include 2
as one of the choices, because it's part of the choices class.
What you could do is define the choices as a constant a bit like this;
STATE_MAX_LENGTH = 2
class States(models.TextChoices):
ALABAMA = 'AL', 'Alabama'
ALASKA = 'AK', 'Alaska'
.....
.....
WISCONSIN = 'WI', 'Wisconsin'
WYOMING = 'WY', 'Wyoming'
class PersonalInfo(models.Model):
state = models.CharField(max_length=STATE_MAX_LENGTH, choices=States.choices, default=States.ALABAMA)
To confirm, here are the choice classes from django;
class Choices(enum.Enum, metaclass=ChoicesMeta):
"""Class for creating enumerated choices."""
def __str__(self):
"""
Use value when cast to str, so that Choices set as model instance
attributes are rendered as expected in templates and similar contexts.
"""
return str(self.value)
class IntegerChoices(int, Choices):
"""Class for creating enumerated integer choices."""
pass
class TextChoices(str, Choices):
"""Class for creating enumerated string choices."""
def _generate_next_value_(name, start, count, last_values):
return name