Using Enum as Model Field Choice in Django
In Django official documentation, they provide 2 examples on how to use predefined options as choices of a particular field.
Examples from Django Official Documentation
The first example defines choices as a Tuple of Tuple, each option being the value of the outer tuple.
The first element in each inner tuple is the value to be set in the model, and the second element being its string representation.
# Example from Django official documentation YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), )
In their second example, they suggest us to define choices as constant in our model class.
# Example from Django official documentation from django.db import models class Student(models.Model): # Constants in Model class FRESHMAN = 'FR' SOPHOMORE = 'SO' JUNIOR = 'JR' SENIOR = 'SR' YEAR_IN_SCHOOL_CHOICES = ( (FRESHMAN, 'Freshman'), (SOPHOMORE, 'Sophomore'), (JUNIOR, 'Junior'), (SENIOR, 'Senior'), ) year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, )
My Preferred Way - Using Enumeration
There is a third option which is my preferred way of defining choices for a Field in Model - Enumeration (or Enum)
What is Enumeration?
Enumeration is a set of symbolic names bound to unique constant values. We will be defining our Enums as a subclass of enum in standard Python library. enum in Python official documentation
In this post, I will walk you through using Enum as choices of field with a simple example. Assume there is a field to identify the language of a Book, given choices of language are English, German, Spanish, and Chinese.
First, we define a class for all choices:
from enum import Enum class LanguageChoice(Enum): # A subclass of Enum DE = "German" EN = "English" CN = "Chinese" ES = "Spanish"
Next, we define our model:
from django.db import models class Book(models.Model): title = models.CharField(max_length=255) language = models.CharField( max_length=5, choices=[(tag, tag.value) for tag in LanguageChoice] # Choices is a list of Tuple )
In our Book model, choices of the language field is a list of Tuple. For simplicity, we use list comprehension to generate our list of choices.
For each tuple in choices, the first element is the value being stored into model, while the second is its human-readable representation.
Now we have defined our Enums and model, how would we use it?
Let's say we want to add a Book entry with language 'DE':
# import your Models and Enums b = Book(title='Deutsch Für Ausländer', language=LanguageChoice.DE) b.save()
Note that how we supply the value for parameter language depends on the first element we defined in the Tuples of the list of choices. We use (tag, tag.value) which tag being an Enum type.
You may ask, "Why using Enum instead of the examples given in Django official documentation?"
- To distinct from any other values within sets of values. For example, we could simple define integer 1-7 for days in a week, what about we have another set of values its representation includes the subset of 1-7?
- Central Repository of predefined values, Enumeration can be used across your entire program, not just your in your models.
When to use Enum?
According to PEP 435, an enumeration are useful for defining an immutable, related set of constant values that may or may not have a semantic meaning. Classic examples are days of the week (Sunday through Saturday) and school assessment grades ('A' through 'D', and 'F'). Other examples include error status values and states within a defined process.
First published on 2017-10-18
Republished on Hackernoon
Love Self-driving technology and machine learning. Community leader in DIYRobocar Hong Kong
How do you compare the enum when the record is read from the DB?
assert book.language == LanguageChoice.DE failed if book is read from DB. It looks like it is comparing a string with a Enum object, which does not work I believe.