#31861: Model field for enumeration types -------------------------------------+------------------------------------- Reporter: George | Owner: nobody Sakkis | Type: New | Status: new feature | Component: Database | Version: 3.1 layer (models, ORM) | Severity: Normal | Keywords: enumeration Triage Stage: | Has patch: 0 Unreviewed | Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | -------------------------------------+------------------------------------- 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 [https://docs.djangoproject.com/en/3.1/ref/models/fields/#enumeration- types Student example]:
{{{ #!python 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. a `models.Choices` subclass. - `field_type` is the underlying ORM field type, e.g. `models.CharField` or `models.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: 1. a new optional `field(**options)` staticmethod on the enumeration type, if present. For example: {{{ #!python 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) }}} 2. Automatically based on the type and values of the enumeration members: - For string values: a `CharField` with `max_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. -- Ticket URL: <https://code.djangoproject.com/ticket/31861> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/050.a20e2e8cd3699ce6a35fc229b29228f7%40djangoproject.com.