Opened 4 years ago
Closed 4 years ago
#31861 closed New feature (duplicate)
Model field for enumeration types
Reported by: | George Sakkis | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.1 |
Severity: | Normal | Keywords: | enumeration |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The new enumeration types in Django 3.0 are a great addition and improvement over the previous choices. On the ORM layer however, only the enumeration values are represented, not the enumeration members. I'd like to suggest a new EnumField
custom field that refers to the actual enumeration member, similar to how ForeignKey
fields refers to the related model object instead of its primary key (or the to_field
in general). Proposed usage for the Student example:
from django.utils.translation import gettext_lazy as _ class Student(models.Model): class YearInSchool(models.TextChoices): FRESHMAN = 'FR', _('Freshman') SOPHOMORE = 'SO', _('Sophomore') JUNIOR = 'JR', _('Junior') SENIOR = 'SR', _('Senior') GRADUATE = 'GR', _('Graduate') year_in_school = models.EnumField(YearInSchool, default=YearInSchool.FRESHMAN) def is_upperclass(self): return self.year_in_school in { self.YearInSchool.JUNIOR, self.YearInSchool.SENIOR, }
In this case, Student.year_in_school
would be a YearInSchool
member, not a two-letter string.
The proposed signature is the following: class EnumField(enum_type, field_type=None, **options)
enum_type
is the enumeration type, i.e. amodels.Choices
subclass.field_type
is the underlying ORM field type, e.g.models.CharField
ormodels.PositiveSmallIntegerField
.- In the simplest implementation, this is a required parameter to be provided by the caller.
- Alternatively, it could be made optional and inferred based on either of the following:
- a new optional
field(**options)
staticmethod on the enumeration type, if present. For example:class YearInSchool(models.TextChoices): FRESHMAN = 'FR', _('Freshman') SOPHOMORE = 'SO', _('Sophomore') JUNIOR = 'JR', _('Junior') SENIOR = 'SR', _('Senior') GRADUATE = 'GR', _('Graduate') @staticmethod def field(**options): options.setdefault("max_length", 2) return models.Charfield(**options)
- Automatically based on the type and values of the enumeration members:
- For string values: a
CharField
withmax_length
the maximum length of the enumeration values. - For integer values: one of {
PositiveSmallIntegerField
,SmallIntegerField
,PositiveIntegerField
,IntegerField
,BigIntegerField
}, the smallest that can represent all the enumeration values. - And so on for other types where there is a natural python type <=> ORM field mapping, e.g.
DateField
for date values. - If the field type cannot be inferred, raise an appropriate exception.
- For string values: a
- a new optional
Duplicate of #24342