Useful Enums for Django

I published my first package to PyPI today. Which is odd, considering that I've been developing stuff in Python for over a decade.

I decided, after doing a bunch of work on various projects, that I needed to scratch a particular Django-related, itch. Namely, that of choices:

    (0, "My Choice"),
    (1, "Another Choice"),
    (2, "A third choice),

Choices have always bugged me, because they encourage you to do hard-coded stuff where you shouldn't be doing hard-coded stuff -- for example:

my_field = models.IntegerField(choices=MY_CHOICES, default=0)

If you ever change MY_CHOICES you've then got to remember what hard-coded nonsense you've got going on everywhere in your codebase. Of course, you could do this:


    (MY_CHOICE_0, "My Choice 0"),
    (MY_CHOICE_1, "My Choice 1"),

Which is better, but strikes me as somewhat annoying -- all that extra defining of constants.

Enter django-useful-enums, which allows you to do this:

from usefulenums import Enum

MyEnum = Enum(
    ("PYTHON_NAME_0", "Display text for this value"),
    ("PYTHON_NAME_1", "Display text for another value"),

Looks the same, sure, but now you can do this:

>>> print(MyEnum.PYTHON_NAME_0)

Which means that you can use standard Python dot notation to access what have become under-the-hood constants:

my_field = models.IntegerField(default=MyEnum.PYTHON_NAME_0)

Still need choices? Okay, no worries, got you covered there too.

>>> print(MyEnum.as_choices())
((0, "Display text for this value"), (1, "Display text for another value"))

And if you've got backwards-compatibility to care about, you can specify your own IDs by passing a three-tuple instead of a two-tuple to Enum():

>>> MyEnum = Enum(
    ("A", "CHOICE_ALPHA", "A is for Alpha"),
    ("B", "CHOICE_BETA", "B is for Beeblebrox"),

>>> print(MyEnum.as_choices())
(('A', 'A is for Alpha'), ('B', 'B is for Beeblebrox'))

You can get django-useful-enums using pip:

pip install django-useful-enums

and you can find the source on Github.