我在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在返回数据时忘记将它们转换回enum。这会导致编码时的不一致,因为django模型过滤器可以查询enum,而属性相等过滤要求我使用enum的字符串表示。
编辑:枚举是从另一个模型类导入的,所以用Django内置的choices类替换它是不可能的。
EDIT2:当我调查这个问题时,我也注意到以下几点:
myobj = Choice.objects.get(id=1)
myobj.awesomeness # <<-- string type
myobj.awesomeness = AwesomeNess.very <<-- object changes type to enum
myobj.save()
myobj2 = Choice.objects.get(id=1) <<-- upon reload from db, the updated value is returned as string
作为一个Django新手,这对我来说是非常危险的,在"如何在Django中使用枚举"中没有提到。我读过的文章。这仅仅是因为我使用的Django版本太旧了吗?
有办法解决这个问题吗?我做错了什么吗?指针赞赏!哦,顺便说一下:这是Django 2.2.24。也许以后的版本会改进枚举支持?
发生这种情况的原因是因为选项调用给定值的str
,因此这意味着它将将"AwesomeNess.slight"
存储为字符串(如果将其设置为默认值)。
从django-3.0开始,你可以使用TextChoices
类[Django-doc],这是完全相同的使用Enum
。因此,您可以定义一个TextChoices
模型:
class Choice(models.Model):
classAwesomNess(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
)