Estoy usando enumeraciones en un modelo Django, como:
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 )Esto funciona bien cuando uso la función de filtro de Django, como:
d = Choice.objects.filter(awesomeness=AwesomeNess.slight)Sin embargo, no funciona si lo hago:
choice_obj = Choice.objects.get(id=1) choice_obj.awesomeness == AwesomeNess.slight # will return False choice_obj.awesomeness == "AwesomeNess.slight" # will return TrueDado que los valores se almacenan como cadenas, parece que Django se olvida de devolverlos a una enumeración al devolver los datos. Esto genera inconsistencias al codificar, ya que los filtros del modelo Django pueden consultar la enumeración, mientras que el filtrado de igualdad de atributos requiere que use la representación de cadena de la enumeración.
EDITAR: las enumeraciones se importan de otra clase de modelo, por lo que reemplazarla con la clase de opciones integrada de Django no es una opción.
EDIT2: Mientras investigo esto, también noto lo siguiente:
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 stringComo usuario novato de Django, esto me parece increíblemente peligroso y no se menciona en ninguno de los artículos de "cómo usar enumeraciones con django" que he leído. ¿Esto se debe simplemente al hecho de que estoy en una versión demasiado antigua de Django?
¿Hay alguna forma de evitar esto? ¿Estoy haciendo algo muy mal? ¡Se agradecen los punteros! oh, bwt: esto es en Django 2.2.24. ¿Quizás las versiones posteriores han mejorado el soporte de enumeración?
La razón por la que esto sucede es porque las opciones llaman a str en el valor que se proporciona, y esto significa que almacenará "AwesomeNess.slight" como una cadena (si está configurada como predeterminada).
Desde django-3.0 , puede trabajar con una clase TextChoices [Django-doc] que es lo mismo que usar Enum . Por lo tanto, puede definir un modelo TextChoices con:
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 ) para versiones anteriores, debe especificar que trabaja con el valor de 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 )