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

Defining Enums

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.

Using Enum

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.

Why Enum?

You may ask, "Why using Enum instead of the examples given in Django official documentation?"

  1. 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?
  2. 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

No Comments Yet