Равенство атрибутов перечисления Django

Я использую перечисления в модели django, например:

class AwesomeNess(Enum):
    slight = "SLIGHT"
    very = "VERY"

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    awesomeness = models.CharField(
        max_length=255,
        choices=[(tag.value, tag.name) for tag in AwesomeNess],
        default=AwesomeNess.slight
    )

Это работает нормально, когда я использую функцию фильтра Django, например:

d = Choice.objects.filter(awesomeness=AwesomeNess.slight)

Однако, он не работает, если я делаю:

choice_obj = Choice.objects.get(id=1)
choice_obj.awesomeness == AwesomeNess.slight # will return False
choice_obj.awesomeness == "AwesomeNess.slight" # will return True

Поскольку значения хранятся в виде строк, похоже, что Django забывает приводить их обратно к перечислению при возврате данных. Это дает несоответствия при кодировании, так как фильтры модели django могут запрашивать по перечислению, в то время как фильтрация равенства атрибутов требует, чтобы я использовал строковое представление перечисления.

EDIT: Перечисления импортированы из другого класса модели, поэтому замена его на встроенный класс выбора Django не является вариантом.

Есть ли способ обойти это? Я делаю что-то очень неправильно? Заранее благодарен! О, bwt: это на Django 2.2.24. Может быть, в более поздних версиях улучшена поддержка перечислений?

Причина, по которой это происходит, заключается в том, что выбор вызывает str на заданном значении, и это означает, что он будет хранить "AwesomeNess.slight" как строку (если это установлено по умолчанию).

Начиная с , вы можете работать с TextChoices классом [Django-doc], что совершенно аналогично использованию Enum. Таким образом, вы можете определить TextChoices модель с помощью:

class Choice(models.Model):

    class AwesomNess(models.TextChoices):
        SLIGHT = 'SLIGHT', 'slight'
        VERY = 'VERY', 'very'

    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    awesomeness = models.CharField(
        max_length=255,
        choices=AwesomeNess.choices,
        default=AwesomeNess.SLIGHT
    )

для старых версий необходимо указать, что вы работаете со значением из AwesomeNess:

class AwesomeNess(Enum):
    slight = 'SLIGHT'
    very = 'VERY'

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    awesomeness = models.CharField(
        max_length=255,
        choices=[(tag.value, tag.name) for tag in AwesomeNess],
        default=AwesomeNess.slight.value
    )
Вернуться на верх