This package lets you use real Python (PEP435-style) enums with Django.
pip install django-choice-enumfields
from enumfields import EnumField
from enumfields import ChoiceEnum # Uses Ethan Furman's "enum34" backport
class Color(ChoiceEnum):
RED = 'r'
GREEN = 'g'
BLUE = 'b'
class MyModel(models.Model):
color = EnumField(Color, max_length=1)
Elsewhere:
m = MyModel.objects.filter(color=Color.RED)
NumEnumField
works identically, but the underlying storage mechanism is
an IntegerField
instead of a CharField
.
from enumfields import EnumField, EnumSubField
from enumfields import ChoiceEnum
class Color(ChoiceEnum):
RED = 'r'
GREEN = 'g'
BLUE = 'b'
class ColorType(ChoiceEnum):
LIGHT = Choice('l', 'light', parents=(Color.RED, Color.BLUE))
DARK = Choice('d', 'dark', parents=(Color.RED, Color.GREEN))
TRANSPARENT = Choice('t', 'transparent', parents=(Color.GREEN))
class MyModel(models.Model):
color = EnumField(Color, max_length=1)
color_type = EnumSubField('color', ColorType, max_length=1)
MyModel(color=Color.RED, color_type=ColorType.LIGHT).full_clean() # OK
MyModel(color=Color.RED, color_type=ColorType.TRANSPARENT).full_clean() # Raise ValidationError
EnumSubField
automatically validates if parents requirement is satisfied.
With EnumSubField
, EnumField
, NumEnumSubField
and NumEnumField
comes validation of initial and allowed transitions between choices out of the box.
from enumfields import EnumField
from enumfields import Choice, ChoiceEnum
class StateFlow(ChoiceEnum):
START = Choice('s', 'start', next={'PROCESSING'})
PROCESSING = Choice('p', 'processing', next={'END'}, initial=False)
END = Choice('e', 'end', next=set(), initial=False)
class MyModel(models.Model):
state = EnumField(StateFlow, max_length=1)
MyModel(state=StateFlow.START).full_clean() # OK
# Raise ValidationError because PROCESSING is not in initial states
MyModel(state=StateFlow.PROCESSING).full_clean()
model = MyModel.objects.create(StateFlow.START)
model.state = StateFlow.END
# Raise ValidationError because END is not next state after START
model.full_clean()
model.state = StateFlow.PROCESSING
model.full_clean() # OK
Call the formfield
method to use an EnumField
directly in a Form
.
class MyForm(forms.Form):
color = EnumField(Color, max_length=1).formfield()
Normally, you just use normal PEP435-style enums, however, django-choice-enumfields also encludes its own version of ChoiceEnum with a few extra bells and whistles. Namely, the smart definition of labels which are used, for example, in admin dropdowns. By default, it will create labels by title-casing your constant names. You can provide custom labels with using Choice to define enum item.
from enumfields import EnumField, ChoiceEnum, Choice # Our own Enum class
class Color(ChoiceEnum):
RED = Choice('r', 'A custom label')
GREEN = 'g'
BLUE = 'b'
class MyModel(models.Model):
color = EnumField(Color, max_length=1)
assert Color.GREEN.label == 'Green'
assert Color.RED.label == 'A custom label'
enumfields.admin.EnumFieldListFilter
is provided to allow using enums in
list_filter
.
from enumfields.admin import EnumFieldListFilter
class MyModelAdmin(admin.ModelAdmin):
list_filter = [('color', EnumFieldListFilter)]