Django 3.0 has built-in support for Enums
Example:
from django.utils.translation import gettext_lazy as _ class Student(models.Model): class YearInSchool(models.TextChoices): FRESHMAN = 'FR', _('Freshman') SOPHOMORE = 'SO', _('Sophomore') JUNIOR = 'JR', _('Junior') SENIOR = 'SR', _('Senior') GRADUATE = 'GR', _('Graduate') year_in_school = models.CharField( max_length=2, choices=YearInSchool.choices, default=YearInSchool.FRESHMAN, )
These work similar to enum from Python’s standard library, but with some modifications:
- Enum member values are a tuple of arguments to use when constructing the concrete data type. Django supports adding an extra string value to the end of this tuple to be used as the human-readable name, or
label
. Thelabel
can be a lazy translatable string. Thus, in most cases, the member value will be a(value, label)
two-tuple. If a tuple is not provided, or the last item is not a (lazy) string, the label is automatically generated from the member name.- A
.label
property is added on values, to return the human-readable name.
A number of custom properties are added to the enumeration classes –.choices
,.labels
,.values
, and.names
– to make it easier to access lists of those separate parts of the enumeration. Use.choices
as a suitable value to pass to choices in a field definition.- The use of
enum.unique()
is enforced to ensure that values cannot be defined multiple times. This is unlikely to be expected in choices for a field.
For more info, check the documentation
Note:
As @Danielle Madeley pointed out, if you try to access the year_in_school
attribute directly Django still returns the raw string instead of the Enum object:
>>> student.year_in_school
'FR'
What I usually do is to create a helper method that returns the Enum object:
class Student(models.Model):
...
def get_year_in_school(self) -> YearInSchool:
# Get value from choices enum
return self.YearInSchool[self.year_in_school]