Hello Django community!
While refactoring my Django application, I realized that I was referencing several models.TextChoices classes from outside the models.py scope — which didn’t feel quite right.
To improve this, I decided to redefine those choices using enum.StrEnum and then generate corresponding models.TextChoices classes from them.
Here’s a small helper function I wrote for that:
@classmethod
def from_enum(cls, enum_cls, name=None):
"""Create a TextChoices class from an existing Enum class."""
attrs = [(member.name, member.value) for member in enum_cls]
return cls(name or enum_cls.__name__, attrs)
I’d love to hear your thoughts, feedback, or any tips on better patterns for managing Django choice fields with enums.
Thanks in advance!
Hallo!
If i understand you - correctly, This’s (simply variant ):
# enums.py
from enum import StrEnum
class UserStatus(StrEnum):
ACTIVE = "active"
INACTIVE = "inactive"
SUSPENDED = "suspended"
class ArticleStatus(StrEnum):
DRAFT = "draft"
PUBLISHED = "published"
ARCHIVED = "archived"
# models.py
from django.db import models
from .enums import UserStatus, ArticleStatus
class User(models.Model):
status = models.CharField(
max_length=20,
choices=TextChoices.from_enum(UserStatus),
default=UserStatus.ACTIVE.value
)
class Article(models.Model):
status = models.CharField(
max_length=20,
choices=TextChoices.from_enum(ArticleStatus),
default=ArticleStatus.DRAFT.value
)
You might also consider a decorator
def django_choices(enum_cls: Type[Enum]) -> Type[TextChoices]:
"""Decorator to convert an Enum to Django TextChoices."""
return TextChoices.from_enum(enum_cls)
# Usage:
# @django_choices
# class Status(StrEnum):
# ACTIVE = "active"
# INACTIVE = "inactive"
My variant which I aften use, it’s (example)
# settings.py
from django.utils.translation import gettext_lazy as _
AGE_RATING_CHOICES = [
("0+", _("Без возрастных ограничений")),
("6+", _("От 6 лет")),
("12+", _("От 12 лет")),
("16+", _("От 16 лет")),
("18+", _("Совершеннолетним")),
]
# views.py
from settings.py import AGE_RATING_CHOICES
class User(models.Model):
status = models.CharField(
max_length=20,
choices=AGE_RATING_CHOICES,
default=AGE_RATING_CHOICES[0]
)
@Tryd0g0lik Thanks for the comment!
I looked through the docs you shared, but I couldn’t find where TextChoices.from_enum() is defined.
Does Django actually provide that method?
This page , doesn/t have the [special this method](django/django/db/models/enums.py at main · django/django · GitHub ]. I show you the simply methods. They are how alternative for chose. You have a list from alias and descript/
P.S.: and i said that -
If i understand you
1 Like