A Django model field that casts enum values to its enum type. Supports all enum types shipped with Django and Python 3 native enum types.
Have you also felt annoyed by having to convert Django's enumeration types back to its type? Using tricks seen below to cast it.
class Suit(models.IntegerChoices):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
class Card(models.Model):
suit_kind = models.IntegerField(choices=Suit.choices, db_column="suit")
@property
def suit(self) -> Suit:
return Suit(self.suit_kind)This is what django-choicefield helps out with. While it additionally supports using
Python's native enum.Enum to express
column values.
import choicefield
from django.db import models
class Suit(models.IntegerChoices):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
class Card(models.Model):
suit = choicefield.ChoiceField(Suit)
instance = Card.objects.create(suit=Suit.CLUB)
assert instance.suit is Suit.CLUBThere's also support for Django's models.TextChoices.
import choicefield
from enum import Enum
from django.db import models
class Suit(int, Enum):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
class Card(models.Model):
suit = choicefield.ChoiceField(Suit)
instance = Card.objects.create(suit=Suit.DIAMOND)
assert instance.suit is Suit.DIAMONDIt's also possible to pass the value of an enum, which will be converted to its corresponding enum instance.
instance = Card(suit=2)
assert instance.suit is Suit.SPADE
instance.save()
assert instance.suit is Suit.SPADE
instance = Card.objects.get(suit=2)
assert instance.suit is Suit.SPADEIf you want to access the stored database values, without conversion to your enum type,
you can use the registered __raw transformer.
Card.objects.values("suit__raw")
# <QuerySet [{'suit__raw': 2}]>In case of e.g. a migration where an enum has changed by, say, removing a value. The database could have values not recognized by the registered enum. Thus it could be necessary to retrieve values without casting them to an enum instance, as it'd raise an error.
It can be done using the __raw transformer while also sidestepping enum validation in
filter values by using
Value expressions
Card.objects.filter(suit=Value(1337)).values_list("suit__raw", flat=True)
# <QuerySet [(1337,)]>Using pip
$ pip install django-choicefieldRunning the whole test matrix
$ toxSetting up a development environment
$ tox -e devRunning the test suite for one environment (non editable)
e.g. Django==4.0.x and Python3.11
$ tox -e django40-py311There are a couple of shortcut commands available using Taskfile, for your convenience.
e.g.
$ task manage -- createsuperuser
$ task runserverAfter installing Taskfile you can run
task --list-all to find all available commands.
django-choicefield is tested according to the table below
| Django version | Python version |
|---|---|
| 5.0.x | ^3.10 |
| 4.2.x | ^3.9 |
| 4.1.x | ^3.9 |
| 4.0.x | ^3.9 |
| 3.2.x | ^3.9 |