Django Choices Field
raw JSON → 4.0.0 verified Fri May 01 auth: no python
A Django field that directly sets/gets Django's TextChoices/IntegerChoices enum values, eliminating manual conversion between enum members and database values. Version 4.0.0 requires Python >=3.10, Django <4.0, and drops support for Python 3.8/3.9. Released irregularly, with breaking changes in v4.0.0 including strict blank/null validation and type checking utilities.
pip install django-choices-field Common errors
error django.core.exceptions.ImproperlyConfigured: ChoicesField 'status' cannot have blank=True without also having null=True ↓
cause Since v4.0.0, blank=True requires null=True to avoid empty string ambiguity with non-string choices.
fix
Add null=True to the field definition, e.g., status = ChoicesField(choices_enum=Status, blank=True, null=True)
error TypeError: 'Status' object is not iterable ↓
cause Trying to iterate over a single enum member instead of using .choices or .values.
fix
Use Status.choices if you need the tuple of choices, or iterate over Status directly: for member in Status: ...
error django.core.exceptions.ValidationError: ['"invalid" is not a valid choice.'] ↓
cause Passing a raw value that is not part of the enum, or missing the enum member conversion.
fix
Assign enum members, e.g., obj.status = MyModel.Status.PUBLISHED, not obj.status = 'PUBLISHED'. For form submission, ensure the form field is also using choices_enum.
Warnings
breaking In v4.0.0, passing blank=True without null=True raises ImproperlyConfigured. Previously it was allowed but could cause data integrity issues. ↓
fix Always set null=True when blank=True, or omit blank=True if not needed.
deprecated Passing choices as a plain list/tuple in the field constructor is deprecated and will be removed in a future version. Use choices_enum instead. ↓
fix Define a ChoicesEnum subclass and pass it to the choices_enum parameter.
gotcha The get_FIELD_display() method works out of the box, but in versions prior to 3.1.1 it was broken for enum fields (returned value instead of label). ↓
fix Upgrade to >=3.1.1, or manually override get_FIELD_display() if stuck on older version.
gotcha ChoicesField does not support null=False and blank=False if the enum does not have a default; you must either set a default or allow null/blank. ↓
fix Provide a default argument (e.g., default=MyEnum.FOO) or set null=True and/or blank=True.
Imports
- ChoicesField
from choices_field import ChoicesField - TypedChoiceFieldMixin
from choices_field import TypedChoiceFieldMixin
Quickstart
from django.db import models
from django.utils.translation import gettext_lazy as _
from choices_field import ChoicesField
class MyModel(models.Model):
class Status(models.TextChoices):
DRAFT = 'DRAFT', _('Draft')
PUBLISHED = 'PUBLISHED', _('Published')
status = ChoicesField(choices_enum=Status, default=Status.DRAFT)
obj = MyModel(status=MyModel.Status.PUBLISHED)
print(obj.status) # MyModel.Status.PUBLISHED
print(obj.status.value) # 'PUBLISHED'