Skip to main content

django-enum

License: MIT Ruff PyPI version PyPI pyversions PyPI djversions PyPI status PyPI - Types Documentation Status Code Cov Test Status Lint Status Published on Django Packages OpenSSF Scorecard OpenSSF Best Practices


Postgres MySQL MariaDB SQLite Oracle


🚨 See migration guide for notes on 1.x to 2.x migration. 🚨

Full and natural support for PEP435 enumerations as Django model fields.

Many packages aim to ease usage of Python enumerations as model fields. Most were superseded when Django provided TextChoices and IntegerChoices types. The motivation for django-enum was to:

  • Work with any Enum including those that do not derive from Django's TextChoices and IntegerChoices.
  • Coerce fields to instances of the Enum type by default.
  • Allow strict adherence to Enum values to be disabled.
  • Handle migrations appropriately. (See migrations)
  • Integrate as fully as possible with Django's existing level of enum support.
  • Support enum-properties to enable richer enumeration types. (A less awkward alternative to dataclass enumerations with more features)
  • Represent enum fields with the smallest possible column type.
  • Support bit field queries using standard Python Flag enumerations.
  • Be as simple and light-weight an extension to core Django as possible.
  • Enforce enumeration value consistency at the database level using check constraints by default.
  • (TODO) Support native database enumeration column types when available.

django-enum provides a new model field type, EnumField, that allows you to treat almost any PEP435 enumeration as a database column. EnumField resolves the correct native Django field type for the given enumeration based on its value type and range. For example, IntegerChoices that contain values between 0 and 32767 become PositiveSmallIntegerField.

from django.db import models
from django_enum import EnumField


class MyModel(models.Model):
    class TextEnum(models.TextChoices):
        VALUE0 = "V0", "Value 0"
        VALUE1 = "V1", "Value 1"
        VALUE2 = "V2", "Value 2"

    class IntEnum(models.IntegerChoices):
        ONE = 1, "One"
        TWO = (
            2,
            "Two",
        )
        THREE = 3, "Three"

    # this is equivalent to:
    #  CharField(max_length=2, choices=TextEnum.choices, null=True, blank=True)
    txt_enum = EnumField(TextEnum, null=True, blank=True)

    # this is equivalent to
    #  PositiveSmallIntegerField(choices=IntEnum.choices, default=IntEnum.ONE.value)
    int_enum = EnumField(IntEnum, default=IntEnum.ONE)

EnumField is more than just an alias. The fields are now assignable and accessible as their enumeration type rather than by-value:

instance = MyModel.objects.create(
    txt_enum=MyModel.TextEnum.VALUE1,
    int_enum=3,  # by-value assignment also works
)

assert instance.txt_enum == MyModel.TextEnum("V1")
assert instance.txt_enum.label == "Value 1"

assert instance.int_enum == MyModel.IntEnum["THREE"]
assert instance.int_enum.value == 3

Flag Support (BitFields)

Flag types are also seamlessly supported! This allows a database column to behave like a bit field and is an alternative to having multiple boolean columns. There are positive performance implications for using a bit field instead of booleans proportional on the size of the bit field and the types of queries you will run against it. For bit fields more than a few bits long the size reduction both speeds up queries and reduces the required storage space. See the documentation for discussion and benchmarks.

class Permissions(IntFlag):
    READ = 1 << 0
    WRITE = 1 << 1
    EXECUTE = 1 << 2


class FlagExample(models.Model):
    permissions = EnumField(Permissions)


FlagExample.objects.create(permissions=Permissions.READ | Permissions.WRITE)

# get all models with RW:
FlagExample.objects.filter(permissions__has_all=Permissions.READ | Permissions.WRITE)

Complex Enumerations

django-enum supports enum types that do not derive from Django's IntegerChoices and TextChoices. This allows us to use other libs like enum-properties which makes possible very rich enumeration fields:

?> pip install enum-properties

from enum_properties import StrEnumProperties
from django.db import models


class TextChoicesExample(models.Model):
    class Color(StrEnumProperties):
        # attribute type hints become properties on each value,
        # and the enumeration may be instantiated from any symmetric
        # property's value

        label: Annotated[str, Symmetric()]
        rgb: Annotated[t.Tuple[int, int, int], Symmetric()]
        hex: Annotated[str, Symmetric(case_fold=True)]

        # properties specified in type hint order after the value
        # name value label       rgb       hex
        RED = "R", "Red", (1, 0, 0), "ff0000"
        GREEN = "G", "Green", (0, 1, 0), "00ff00"
        BLUE = "B", "Blue", (0, 0, 1), "0000ff"

    color = EnumField(Color)


instance = TextChoicesExample.objects.create(color=TextChoicesExample.Color("FF0000"))
assert instance.color == TextChoicesExample.Color("Red")
assert instance.color == TextChoicesExample.Color("R")
assert instance.color == TextChoicesExample.Color((1, 0, 0))

# direct comparison to any symmetric value also works
assert instance.color == "Red"
assert instance.color == "R"
assert instance.color == (1, 0, 0)

# save by any symmetric value
instance.color = "FF0000"

# access any enum property right from the model field
assert instance.color.hex == "ff0000"

# this also works!
assert instance.color == "ff0000"

# and so does this!
assert instance.color == "FF0000"

instance.save()

# filtering works by any symmetric value or enum type instance
assert (
    TextChoicesExample.objects.filter(color=TextChoicesExample.Color.RED).first()
    == instance
)

assert TextChoicesExample.objects.filter(color=(1, 0, 0)).first() == instance

assert TextChoicesExample.objects.filter(color="FF0000").first() == instance

While they should be unnecessary if you need to integrate with code that expects an interface fully compatible with Django's TextChoices and IntegerChoices django-enum provides TextChoices, IntegerChoices, FlagChoices and FloatChoices types that derive from enum-properties and Django's Choices. So the above enumeration could also be written:

from django_enum.choices import TextChoices


class Color(TextChoices):
    # label is added as a symmetric property by the base class

    rgb: Annotated[t.Tuple[int, int, int], Symmetric()]
    hex: Annotated[str, Symmetric(case_fold=True)]

    # name value label       rgb       hex
    RED = "R", "Red", (1, 0, 0), "ff0000"
    GREEN = "G", "Green", (0, 1, 0), "00ff00"
    BLUE = "B", "Blue", (0, 0, 1), "0000ff"

Installation

  1. Clone django-enum from GitHub or install a release off pypi:
   pip install django-enum

django-enum has several optional dependencies that are not installed by default. EnumField works seamlessly with all Django apps that work with model fields with choices without any additional work. Optional integrations are provided with several popular libraries to extend this basic functionality, these include:

Database Support

Postgres MySQL MariaDB SQLite Oracle

Like with Django, PostgreSQL is the preferred database for support. The full test suite is run against all combinations of currently supported versions of Django, Python, and PostgreSQL as well as psycopg3 and psycopg2. The other RDBMS supported by Django are also tested including SQLite, MySQL, MariaDB and Oracle. For these RDBMS (with the exception of Oracle, tests are run against the minimum and maximum supported version combinations to maximize coverage breadth.

See the latest test runs for our current test matrix

For Oracle, only the latest version of the free database is tested against the minimum and maximum supported versions of Python, Django and the cx-Oracle driver.

Further Reading

Consider using django-render-static to make your enumerations DRY across the full stack!

Please report bugs and discuss features on the issues page.

Contributions are encouraged!

Full documentation at read the docs.

Metadata

Release files for django-enum 2.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-enum 2.5.0
File Size Uploaded
django_enum-2.5.0.tar.gz 690.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-enum 2.5.0
File Interpreter ABI Platform
django_enum-2.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 729.5 kB

Release files / django_enum-2.5.0.tar.gz

Download URL django_enum-2.5.0.tar.gz
Size 690.2 kB
Tags Source
SHA-256 checksum
How to use checksums
23706ab296486c8f1b3ba5dda95125ba2a9161ce73f89bd16b4328d434853ebc
BLAKE2b-256 checksum
How to use checksums
50aa368f1cd852d518c812a7289de8766d15016eca8114ebaa16c75e56feaa2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release files / django_enum-2.5.0-py3-none-any.whl

Download URL django_enum-2.5.0-py3-none-any.whl
Size 39.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36a6caa6bba5daf2d08709d6845a8824d6c7a862021ab65c39f7d5289d5c4bb2
BLAKE2b-256 checksum
How to use checksums
ec69f7ccb7cc9b54821f43d0c30cf3b38261cc9d6880e06b5ff2bab7f578bc4a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.5.0 This release

2 release files

2.4.3

2 release files

2.4.2

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.5

2 release files

2.2.4

2 release files

2.2.3

2 release files

2.2.2

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.3.3

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page