Using models instead of choices for enumerations in Django

Question:

I am currently building a simple application in Django and am trying to settle on a good model design.

First Approach

In the Django documentation and many blog posts I have read, the choice keyword argument is recommended. This would be implemented in my (simplified) noun model like so:

class Noun(models.Model):
    FEMININE = 0
    MASCULINE = 1
    NEUTER = 2
    COMMON = 3
    GENDER_TYPE = (
        (FEMININE, "Feminine"),
        (MASCULINE, "Masculine"),
        (NEUTER, "Neuter"),
        (COMMON, "Common"),
    )
    stem = models.CharField(max_length=200)
    gender = models.IntegerField(choices=GENDER_TYPE, default=Noun.COMMON)

Second Approach

When I walked across the hallway and spoke to a db admin friend about how he would indicate enumerations in a database, he acknowledged debate but said that he would make a table for each enumeration and reference it by foreign key. This approach maps almost exactly to the following models:

class Gender(models.Model):
    short_name = models.CharField(max_length=1) # M, F, N, or C
    description = models.CharField(max_length=20) # Masculine, Feminine, Neuter, or Common

class Noun(models.Model):
    stem = models.CharField(max_length=200)
    gender = models.ForeignKey(Gender, on_delete=models.CASCADE)

I am trying to weigh the relative merits of each approach. Here are the pro’s and con’s I can discern:

First Approach

  1. Encapsulated
  2. No need to import a “Gender” model
  3. Does not require extra step of populating enumeration values in the database
  4. Easier to read in the code: I do not need to look at the database to see the valid values

Second Approach

  1. Much more flexible: I can change all feminine words to masculine in one step, or add a new gender without having to modify the noun table
  2. The logic is enforced by a foreign key constraint rather than the code, preserving data integrity

So, my question: Am I missing something obvious about why one approach is invalid? If both approaches are valid, which approach is better?

Asked By: brianpck

||

Answers:

Both approaches are valid. To decide on one, you should consider mostly two points: how many choices you have, and how likely they are to change in the future.

So, if there are few choices and they are unlikely to change often, use choices instead of a foreign key – it will be better from a performance point of view. If there are many choices or they change often – go for a foreign key.

In this case with genders, I would choose choices. Even if they change in the future – existing ones most likely won’t be affected.

Answered By: Nikita

Your understanding of both approaches pros and cons is correct. In the case of a small project you can use any approach without any problems at all. However, if you expect your project to be large enough, you should pay attention to these comments:

  1. If the choices list might grow in time it will be easier to have it as a Gender model.
  2. If the choices list is undoubtedly constant – use gender field with choices attribute. This will save you some time on making a query of an unnecessary Gender model.
Answered By: chem1st
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.