Django choices design

Hi, was wondering if we define all model choices in a single centralized file outside of models.py, would there be any potential downside? Anyone can share their experience on this approach? Is this recommended?

Typical way of defining model choices

# models.py
from django.db import models


class ExampleClass(models.Model):
    EXAMPLE_CHOICES = [
        ("CHOICE1", "CHOICE1"),
        ("CHOICE2", "CHOICE2"),
        ("CHOICE3", "CHOICE3"),
    ]

    example_field = models.CharField(choices=EXAMPLE_CHOICES)

This works if choices is outside model class

# models.py
from django.db import models


EXAMPLE_CHOICES = [
    ("CHOICE1", "CHOICE1"),
    ("CHOICE2", "CHOICE2"),
    ("CHOICE3", "CHOICE3"),
]


class ExampleClass(models.Model):
    example_field = models.CharField(choices=EXAMPLE_CHOICES)

Thinking of this

# choices.py
EXAMPLE_CHOICES = [
    ("CHOICE1", "CHOICE1"),
    ("CHOICE2", "CHOICE2"),
    ("CHOICE3", "CHOICE3"),
]

# models.py
from django.db import models
from centralizedbasefolder.choices import *

class ExampleClass(models.Model):
    example_field = models.CharField(choices=EXAMPLE_CHOICES)

Reason for doing this is because it will be easier to access choices if you need to:

# instead of
> from example1app import ExampleClass
> from example2app import ExampleClass2
> from example3app import ExampleClass3
> ExampleClass.EXAMPLE_CHOICES
> ExampleClass2.EXAMPLE_CHOICES2
> ExampleClass3.EXAMPLE_CHOICES3

# you can do
> from centralizedbasefolder.choices import *
> EXAMPLE_CHOICES
> EXAMPLE_CHOICES2
> EXAMPLE_CHOICES3

This is a fine approach, between apps or if you are splitting up your models.py files into a package.

P.S. I recommend you use the enumeration types added in Django 3.0: Moving to Django 3.0’s Field.choices Enumeration Types - Adam Johnson . The docs could really do with some work to emphasize them.

I normally use a naming scheme like <ModelName><ChoiceName> e.g. BookType. For choices that are reused between models I try to use some kind of base/parent model name, even if it doesn’t really exist e.g. ReadableType

Thanks, just followed your advice, change all choices to enum class.

Btw, any tips / rules on deciding when to use enum class?

I always use enum classes over the list-of-tuples method.