Solución:
Es bastante común definir constantes para los valores enteros de la siguiente manera:
class Task(models.Model):
CANCELLED = -1
REQUIRES_ATTENTION = 0
WORK_IN_PROGRESS = 1
COMPLETE = 2
Status = (
(CANCELLED, 'Cancelled'),
(REQUIRES_ATTENTION, 'Requires attention'),
(WORK_IN_PROGRESS, 'Work in progress'),
(COMPLETE, 'Complete'),
)
status = models.IntegerField(choices=Status, default=REQUIRES_ATTENTION)
Moviendo las constantes y Status
dentro de la clase de modelo, mantiene más limpio el espacio de nombres del módulo y, como beneficio adicional, puede consultar Task.COMPLETE
donde sea que importe el Task
modelo.
CANCELED, ATTENTION, WIP, COMPLETE = range(-1, 3)
Status = (
(CANCELED, 'Cancelled'),
(ATTENTION, 'Requires attention'),
(WIP, 'Work in progress'),
(COMPLETE, 'Complete'),
)
class Task(models.Model):
status = models.IntegerField(choices=Status, default=CANCELED)
Tenga en cuenta que, como señalaron otros, la forma correcta es poner estas variables dentro de su clase Model. Así es también como lo hace el ejemplo oficial de django.
Solo hay una razón por la que querría ponerlo fuera del espacio de nombres de la clase y es solo si esta semántica es compartida por igual por otros modelos de su aplicación. es decir, no puedes decidir en qué específico modelo al que pertenecen.
Aunque no parece que este sea el caso en su ejemplo particular.
Python 3.4+: Enum
Usted escribe “Si es posible, me gustaría evitar el uso de un número por completo”.
y, de hecho, una representación con nombre es claramente más pitónica. Sin embargo, una cadena desnuda es susceptible a errores tipográficos.
Python 3.4 introduce un módulo llamado
enum
Proporcionar Enum
y IntEnum
pseudoclases que ayudan con esta situación. Con él, su ejemplo podría funcionar de la siguiente manera:
# in Python 3.4 or later:
import enum
class Status(enum.IntEnum):
Cancelled = -1,
Requires_attention = 0,
Work_in_progress = 1,
Complete = 2
def choiceadapter(enumtype):
return ((item.value, item.name.replace('_', ' ')) for item in enumtype)
class Task(models.Model):
status = models.IntegerField(choices=choiceadapter(Status),
default=Status.Requires_attention.value)
y una vez que el equipo de Django retoma Enum
, los
choiceadapter
incluso se integrará en Django.