Provides an enumeration Django model field (using IntegerField) with reusable enums and transition validation.
Currently, we test Django versions 2.2-4.1 and Python versions 3.7-3.11.
Install django-enumfield in your Python environment:
$ pip install django-enumfieldUpgrading from django-enumfield 1.x?See the migration guide
For use with Django versions prior to 1.8 use version
1.2.1
For use with Django versions prior to 1.11 use version
1.5
Create an Enum-class and pass it as first argument to the Django model EnumField.
fromdjango.dbimportmodelsfromdjango_enumfieldimportenumclassBeerStyle(enum.Enum):
LAGER=0STOUT=1WEISSBIER=2classBeer(models.Model):
style=enum.EnumField(BeerStyle, default=BeerStyle.LAGER)
# Use .get to get enum values from either name or intsprint(BeerStyle.get("LAGER")) # <BeerStyle.LAGER: 0>print(BeerStyle.get(1)) # <BeerStyle.STOUT: 1>print(BeerStyle.get(BeerStyle.WEISSBIER)) # <BeerStyle.WEISSBIER: 2># It's also possible to use the normal enum way to get the valueprint(BeerStyle(1)) # <BeerStyle.STOUT: 1>print(BeerStyle["LAGER"]) # <BeerStyle.LAGER: 0># The enum value has easy access to their value and nameprint(BeerStyle.LAGER.value) # 0print(BeerStyle.LAGER.name) # "LAGER"For more information about Python 3 enums
(which our Enum inherits, IntEnum to be specific)
checkout the docs.
You can also set default value on your enum class using __default__
attribute
fromdjango.dbimportmodelsfromdjango_enumfieldimportenumclassBeerStyle(enum.Enum):
LAGER=0STOUT=1WEISSBIER=2__default__=LAGERclassBeerStyleNoDefault(enum.Enum):
LAGER=0classBeer(models.Model):
style_default_lager=enum.EnumField(BeerStyle)
style_default_stout=enum.EnumField(BeerStyle, default=BeerStyle.STOUT)
style_default_null=enum.EnumField(BeerStyleNoDefault, null=True, blank=True)
# When you set __default__ attribute, you can access default value via# `.default()` method of your enum classassertBeerStyle.default() ==BeerStyle.LAGERbeer=Beer.objects.create()
assertbeer.style_default_larger==BeerStyle.LAGERassertbeer.style_default_stout==BeerStyle.STOUTassertbeer.style_default_nullisNoneYou can use your own labels for Enum items
fromdjango.utils.translationimportgettext_lazyfromdjango_enumfieldimportenumclassAnimals(enum.Enum):
CAT=1DOG=2SHARK=3__labels__= {
CAT: gettext_lazy("Cat"),
DOG: gettext_lazy("Dog"),
}
print(Animals.CAT.label) # "Cat"print(Animals.SHARK.label) # "SHARK"# There's also classmethods for getting the labelprint(Animals.get_label(2)) # "Dog"print(Animals.get_label("DOG")) # "Dog"The Enum-class provides the possibility to use transition validation.
fromdjango.dbimportmodelsfromdjango_enumfieldimportenumfromdjango_enumfield.exceptionsimportInvalidStatusOperationErrorclassPersonStatus(enum.Enum):
ALIVE=1DEAD=2REANIMATED=3__transitions__= {
DEAD: (ALIVE,), # Can go from ALIVE to DEADREANIMATED: (DEAD,) # Can go from DEAD to REANIMATED
}
classPerson(models.Model):
status=enum.EnumField(PersonStatus)
# These transitions state that a PersonStatus can only go to DEAD from ALIVE and to REANIMATED from DEAD.person=Person.objects.create(status=PersonStatus.ALIVE)
try:
person.status=PersonStatus.REANIMATEDexceptInvalidStatusOperationError:
print("Person status can not go from ALIVE to REANIMATED")
else:
# All goodperson.save()The Enum-class can also be used without the EnumField. This is very useful in Django form ChoiceFields.
fromdjangoimportformsfromdjango_enumfieldimportenumfromdjango_enumfield.forms.fieldsimportEnumChoiceFieldclassGenderEnum(enum.Enum):
MALE=1FEMALE=2__labels__= {
MALE: "Male",
FEMALE: "Female",
}
classPersonForm(forms.Form):
gender=EnumChoiceField(GenderEnum)Rendering PersonForm in a template will generate a select-box with "Male" and "Female" as option labels for the gender field.
Make sure black and isort is installed in your env with pip install -e .[dev].
Before committing run make format to apply black and isort to all files.