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.

1
  • 1
    Check my answer here for a way to add a class constant to an Enum. Commented Jun 26, 2021 at 22:22

1 Answer 1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.