4
4
Django Enum
5
5
===========
6
6
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 |
8
9
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
+ ----
12
11
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.
14
70
* 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)
19
75
* 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.
21
80
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 >`_.
27
86
28
- .. code :: python
87
+ .. code-block :: python
29
88
30
89
from django.db import models
31
90
from django_enum import EnumField
@@ -49,14 +108,14 @@ values between 0 and 32767 become `PositiveSmallIntegerField <https://docs.djang
49
108
txt_enum = EnumField(TextEnum, null = True , blank = True )
50
109
51
110
# 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 )
54
113
55
114
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: **
58
117
59
- .. code :: python
118
+ .. code-block :: python
60
119
61
120
instance = MyModel.objects.create(
62
121
txt_enum = MyModel.TextEnum.VALUE1 ,
@@ -70,24 +129,64 @@ accessible as their enumeration type rather than by-value:**
70
129
assert instance.int_enum.value == 3
71
130
72
131
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 ):
76
152
77
- .. code :: python
153
+ permissions = EnumField(Permissions)
78
154
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
81
176
from django.db import models
82
177
83
178
class TextChoicesExample (models .Model ):
84
179
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 )]
86
185
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"
91
190
92
191
# any named s() values in the Enum's inheritance become properties on
93
192
# each value, and the enumeration value may be instantiated from the
@@ -130,49 +229,78 @@ enum-properties_ which makes possible very rich enumeration fields.
130
229
131
230
assert TextChoicesExample.objects.filter(color = ' FF0000' ).first() == instance
132
231
133
- .. note ::
134
232
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:
138
237
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
141
241
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"
144
253
145
- `Full documentation at read the docs. <https://django-enum.readthedocs.io/en/latest/ >`_
146
254
147
255
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
149
263
150
- 1. Clone django-enum from GitHub _ or install a release off PyPI _ :
151
264
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.
153
269
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 _.
155
272
273
+ .. code-block :: console
156
274
157
- .. note ::
275
+ ?> pip install enum-properties
276
+ ?> pip install django-filter
277
+ ?> pip install djangorestframework
158
278
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.
164
279
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
+ ======================
167
282
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.
169
288
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 >`_.
173
302
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!
176
304
177
305
178
306
.. toctree ::
0 commit comments