1

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.

Amistad
  • 7,100
  • 13
  • 48
  • 75
  • 1
    Check [my answer here](https://stackoverflow.com/a/18035135/208880) for a way to add a class constant to an Enum. – Ethan Furman Jun 26 '21 at 22:22

1 Answers1

2

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
markwalker_
  • 12,078
  • 7
  • 62
  • 99