44Django Enum
55===========
66
7- Full and natural support for enumerations _ as Django model fields.
7+ |MIT license | |Ruff | |PyPI version fury.io | |PyPI pyversions | |PyPi djversions | |PyPI status |
8+ |Documentation Status | |Code Cov | |Test Status |
89
9- Many packages aim to ease usage of Python enumerations as model fields. Most
10- were made obsolete when Django provided TextChoices _ and IntegerChoices _
11- types. The motivation for django-enum was to:
10+ ----
1211
13- * Always automatically coerce fields to instances of the Enum type.
12+ |Postgres | |MySQL | |MariaDB | |SQLite | |Oracle |
13+
14+ .. |MIT license | image :: https://img.shields.io/badge/License-MIT-blue.svg
15+ :target: https://lbesson.mit-license.org/
16+
17+ .. |Ruff | image :: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
18+ :target: https:://github.com/astral-sh/ruff
19+
20+ .. |PyPI version fury.io | image :: https://badge.fury.io/py/django-enum.svg
21+ :target: https://pypi.python.org/pypi/django-enum/
22+
23+ .. |PyPI pyversions | image :: https://img.shields.io/pypi/pyversions/django-enum.svg
24+ :target: https://pypi.python.org/pypi/django-enum/
25+
26+ .. |PyPI djversions | image :: https://img.shields.io/pypi/djversions/django-enum.svg
27+ :target: https://pypi.org/project/django-enum/
28+
29+ .. |PyPI status | image :: https://img.shields.io/pypi/status/django-enum.svg
30+ :target: https://pypi.python.org/pypi/django-enum
31+
32+ .. |Documentation Status | image :: https://readthedocs.org/projects/django-enum/badge/?version=latest
33+ :target: http://django-enum.readthedocs.io/?badge=latest/
34+
35+ .. |Code Cov | image :: https://codecov.io/gh/bckohan/django-enum/branch/main/graph/badge.svg?token=0IZOKN2DYL
36+ :target: https://codecov.io/gh/bckohan/django-enum
37+
38+ .. |Test Status | image :: https://github.com/bckohan/django-enum/workflows/test/badge.svg
39+ :target: https://github.com/bckohan/django-enum/actions/workflows/test.yml
40+
41+ .. |Lint Status | image :: https://github.com/bckohan/django-enum/workflows/lint/badge.svg
42+ :target: https://github.com/bckohan/django-enum/actions/workflows/lint.yml
43+
44+ .. |Postgres | image :: https://img.shields.io/badge/Postgres-9.6%2B-blue
45+ :target: https://www.postgresql.org/
46+
47+ .. |MySQL | image :: https://img.shields.io/badge/MySQL-5.7%2B-blue
48+ :target: https://www.mysql.com/
49+
50+ .. |MariaDB | image :: https://img.shields.io/badge/MariaDB-10.2%2B-blue
51+ :target: https://mariadb.org/
52+
53+ .. |SQLite | image :: https://img.shields.io/badge/SQLite-3.8%2B-blue
54+ :target: https://www.sqlite.org/
55+
56+ .. |Oracle | image :: https://img.shields.io/badge/Oracle-18%2B-blue
57+ :target: https://www.oracle.com/database/
58+
59+ ----
60+
61+ Full and natural support for enumerations _ as Django _ model fields.
62+
63+ Many packages aim to ease usage of Python enumerations as model fields. Most were superseded when
64+ Django provided ``TextChoices `` and ``IntegerChoices `` types. The motivation for django-enum _ was
65+ to:
66+
67+ * Work with any Python PEP 435 Enum including those that do not derive from Django's
68+ ``TextChoices `` and ``IntegerChoices ``.
69+ * Coerce fields to instances of the Enum type by default.
1470* Allow strict adherence to Enum values to be disabled.
15- * Be compatible with Enum classes that do not derive from Django's Choices.
16- * Handle migrations appropriately. (See ` migrations < https://django- enum.readthedocs.io/en/latest/usage.html#migrations >`_)
17- * Integrate as fully as possible with Django _'s existing level of enum support.
18- * Integrate with enum-properties _ to enable richer enumeration types.
71+ * Handle migrations appropriately. (See :ref: ` migrations `)
72+ * Integrate as fully as possible with Django's existing level of enum support.
73+ * Support enum-properties _ to enable richer enumeration types. (A less awkward alternative to
74+ dataclass enumerations with more features)
1975* Represent enum fields with the smallest possible column type.
20- * Be as simple and light-weight an extension to core Django as possible.
76+ * Support bit mask queries using standard Python Flag enumerations.
77+ * Be as simple and light-weight an extension to core Django _ as possible.
78+ * Enforce enumeration value consistency at the database level using check constraints by default.
79+ * (TODO) Support native database enumeration column types when available.
2180
22- django-enum works in concert with Django _'s built in TextChoices _ and
23- IntegerChoices _ to provide a new model field type, ``EnumField ``, that
24- resolves the correct native Django _ field type for the given enumeration based
25- on its value type and range. For example, IntegerChoices _ that contain
26- values between 0 and 32767 become `PositiveSmallIntegerField <https://docs.djangoproject.com/en/stable/ref/models/fields/#positivesmallintegerfield >`_.
81+ django-enum _ provides a new model field type, `` EnumField ``, that allows you to treat almost any
82+ PEP 435 enumeration as a database column. ``EnumField `` resolves the correct native Django _ field
83+ type for the given enumeration based on its value type and range. For example, `` IntegerChoices ``
84+ that contain values between 0 and 32767 become
85+ `PositiveSmallIntegerField <https://docs.djangoproject.com/en/stable/ref/models/fields/#positivesmallintegerfield >`_.
2786
28- .. code :: python
87+ .. code-block :: python
2988
3089 from django.db import models
3190 from django_enum import EnumField
@@ -49,14 +108,14 @@ values between 0 and 32767 become `PositiveSmallIntegerField <https://docs.djang
49108 txt_enum = EnumField(TextEnum, null = True , blank = True )
50109
51110 # this is equivalent to
52- # PositiveSmallIntegerField(choices=IntEnum.choices)
53- int_enum = EnumField(IntEnum)
111+ # PositiveSmallIntegerField(choices=IntEnum.choices, default=IntEnum.ONE.value )
112+ int_enum = EnumField(IntEnum, default = IntEnum. ONE )
54113
55114
56- ``EnumField `` **is more than just an alias. The fields are now assignable and
57- accessible as their enumeration type rather than by-value: **
115+ ``EnumField `` **is more than just an alias. The fields are now assignable and accessible as their
116+ enumeration type rather than by-value: **
58117
59- .. code :: python
118+ .. code-block :: python
60119
61120 instance = MyModel.objects.create(
62121 txt_enum = MyModel.TextEnum.VALUE1 ,
@@ -70,24 +129,64 @@ accessible as their enumeration type rather than by-value:**
70129 assert instance.int_enum.value == 3
71130
72131
73- `django-enum <https://django-enum.readthedocs.io/en/latest/ >`_ also provides
74- IntegerChoices _ and TextChoices _ types that extend from
75- enum-properties _ which makes possible very rich enumeration fields.
132+ Flag Support
133+ ============
134+
135+ Flag _ types are also seamlessly supported! This allows a database column to behave like a bit mask
136+ and is an alternative to multiple boolean columns. There are mostly positive performance
137+ implications for using a bit mask instead of booleans depending on the size of the bit mask and the
138+ types of queries you will run against it. For bit masks more than a few bits long the size
139+ reduction both speeds up queries and reduces the required storage space. See the documentation for
140+ :ref: `discussion and benchmarks <flag_performance >`.
141+
142+ .. code-block :: python
143+
144+ class Permissions (IntFlag ):
145+
146+ READ = 1 ** 2
147+ WRITE = 2 ** 2
148+ EXECUTE = 3 ** 2
149+
150+
151+ class FlagExample (models .Model ):
76152
77- .. code :: python
153+ permissions = EnumField(Permissions)
78154
79- from enum_properties import s
80- from django_enum import TextChoices # use instead of Django's TextChoices
155+
156+ FlagExample.objects.create(permissions = Permissions.READ | Permissions.WRITE )
157+
158+ # get all models with RW:
159+ FlagExample.objects.filter(permissions__has_all = Permissions.READ | Permissions.WRITE )
160+
161+
162+ Complex Enumerations
163+ ====================
164+
165+ django-enum _ supports enum types that do not derive from Django's ``IntegerChoices `` and
166+ ``TextChoices ``. This allows us to use other libs like enum-properties _ which makes possible very
167+ rich enumeration fields:
168+
169+ .. code-block :: console
170+
171+ ?> pip install enum-properties
172+
173+ .. code-block :: python
174+
175+ from enum_properties import StrEnumProperties
81176 from django.db import models
82177
83178 class TextChoicesExample (models .Model ):
84179
85- class Color (TextChoices , s (' rgb' ), s (' hex' , case_fold = True )):
180+ class Color (StrEnumProperties ):
181+
182+ label: Annotated[str , Symmetric()]
183+ rgb: Annotated[t.Tuple[int , int , int ], Symmetric()]
184+ hex : Annotated[str , Symmetric(case_fold = True )]
86185
87- # name value label rgb hex
88- RED = ' R ' , ' Red' , (1 , 0 , 0 ), ' ff0000'
89- GREEN = ' G ' , ' Green' , (0 , 1 , 0 ), ' 00ff00'
90- BLUE = ' B ' , ' Blue' , (0 , 0 , 1 ), ' 0000ff'
186+ # name value label rgb hex
187+ RED = " R " , " Red" , (1 , 0 , 0 ), " ff0000"
188+ GREEN = " G " , " Green" , (0 , 1 , 0 ), " 00ff00"
189+ BLUE = " B " , " Blue" , (0 , 0 , 1 ), " 0000ff"
91190
92191 # any named s() values in the Enum's inheritance become properties on
93192 # each value, and the enumeration value may be instantiated from the
@@ -130,49 +229,78 @@ enum-properties_ which makes possible very rich enumeration fields.
130229
131230 assert TextChoicesExample.objects.filter(color = ' FF0000' ).first() == instance
132231
133- .. note ::
134232
135- Consider using
136- `django-render-static <https://pypi.org/project/django-render-static/ >`_
137- to make your enumerations DRY _ across the full stack!
233+ While they should be unnecessary if you need to integrate with code that expects an interface fully
234+ compatible with Django's ``TextChoices `` and ``IntegerChoices `` django-enum _ provides
235+ ``TextChoices ``, ``IntegerChoices ``, ``FlagChoices `` and ``FloatChoices `` types that derive from
236+ enum-properties _ and Django's ``Choices ``. So the above enumeration could also be written:
138237
139- Please report bugs and discuss features on the
140- `issues page <https://github.com/bckohan/django-enum/issues >`_.
238+ .. code-block :: python
239+
240+ from django_enum.choices import TextChoices
141241
142- `Contributions <https://github.com/bckohan/django-enum/blob/main/CONTRIBUTING.rst >`_
143- are encouraged!
242+ class Color (TextChoices ):
243+
244+ # label is added as a symmetric property by the base class
245+
246+ rgb: Annotated[t.Tuple[int , int , int ], Symmetric()]
247+ hex : Annotated[str , Symmetric(case_fold = True )]
248+
249+ # name value label rgb hex
250+ RED = " R" , " Red" , (1 , 0 , 0 ), " ff0000"
251+ GREEN = " G" , " Green" , (0 , 1 , 0 ), " 00ff00"
252+ BLUE = " B" , " Blue" , (0 , 0 , 1 ), " 0000ff"
144253
145- `Full documentation at read the docs. <https://django-enum.readthedocs.io/en/latest/ >`_
146254
147255 Installation
148- ------------
256+ ============
257+
258+ 1. Clone django-enum from GitHub _ or install a release off PyPI _:
259+
260+ .. code-block :: console
261+
262+ ?> pip install django-enum
149263
150- 1. Clone django-enum from GitHub _ or install a release off PyPI _ :
151264
152- .. code :: bash
265+ django-enum _ has several optional dependencies that are not pulled in by default. ``EnumFields ``
266+ work seamlessly with all Django apps that work with model fields with choices without any
267+ additional work. Optional integrations are provided with several popular libraries to extend this
268+ basic functionality.
153269
154- pip install django-enum
270+ Integrations are provided that leverage enum-properties _ to make enumerations do more work and to
271+ provide extended functionality for django-filter _ and djangorestframework _.
155272
273+ .. code-block :: console
156274
157- .. note ::
275+ ?> pip install enum-properties
276+ ?> pip install django-filter
277+ ?> pip install djangorestframework
158278
159- ``django-enum `` has several optional dependencies that are not pulled in
160- by default. ``EnumFields `` work seamlessly with all Django apps that
161- work with model fields with choices without any additional work. Optional
162- integrations are provided with several popular libraries to extend this
163- basic functionality.
164279
165- Integrations are provided that leverage enum-properties _ to make enumerations
166- do more work and to provide extended functionality for django-filter _ and DRF _.
280+ Continuous Integration
281+ ======================
167282
168- .. code :: bash
283+ Like with Django, Postgres is the preferred database for support. The full test suite is run
284+ against all combinations of currently supported versions of Django, Python, and Postgres as well as
285+ psycopg3 and psycopg2. The other RDBMS supported by Django are also tested including SQLite, MySQL,
286+ MariaDB and Oracle. For these RDBMS (with the exception of Oracle), tests are run against the
287+ minimum and maximum supported version combinations to maximize coverage breadth.
169288
170- pip install enum-properties
171- pip install django-filter
172- pip install djangorestframework
289+ **See the ** `latest test runs <https://github.com/bckohan/django-enum/actions/workflows/test.yml >`_
290+ **for our current test matrix **
291+
292+ *For Oracle, only the latest version of the free database is tested against the minimum and
293+ maximum supported versions of Python, Django and the cx-Oracle driver. *
294+
295+ Further Reading
296+ ===============
297+
298+ Consider using django-render-static _ to make your enumerations DRY _ across the full stack!
299+
300+ Please report bugs and discuss features on the
301+ `issues page <https://github.com/bckohan/django-enum/issues >`_.
173302
174- If features are utilized that require a missing optional dependency an
175- exception will be thrown.
303+ `Contributions <https://github.com/bckohan/django-enum/blob/main/CONTRIBUTING.md >`_ are encouraged!
176304
177305
178306.. toctree ::
0 commit comments