Opened 19 months ago

Last modified 18 months ago

#34388 closed New feature

Added support for direct usage of Choices classes on model fields — at Initial Version

Reported by: T. Franzel Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: David Wobrock, Adam Johnson Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi,

I would like to propose a feature addition on how Choices are handled when used on model fields. Currently, Field.choices only accepts iterables. This has 2 shortcommings imho:

  1. - Rejecting a Choices class as argument to Field(choices=...) seems counter-intuitive. Providing the class directly currently results in a fields.E005 error.
    • To make this more pythonic, the field should also accept the Choice class directly and deal with the variation internally.
    • I really can't come up with a scenario where a user would want a different behavior or rather that a user would be surprised by the implicit resolution.
  1. By forcing the user to expand the Choices class manually, essentially all meta information is lost. Downstream packages may benefit from this lost information.
    • Specifically, as maintainer of drf-spectcular (OpenAPI generator for DRF), I am interested in the name of the choice set (e.g. Suit, Vehicle, Gender) and potentially also the docstring. This would greatly improve OpenAPI generation of choice sets and take out the unnecessary guesswork to find a proper name. (And if anyone wonders, the model field name is not a good candidate for a choice set name.)


This PR allows to use Choices classes directly as argument, while being transparent. No behavioral changes otherwise.

I marked this as dev, but it would be awesome if it could still slip into 4.2. Not sure if the feature window is still open, but this is more or less a trivial and backwards-compatible change with little risk. PR is still missing some docs, which I will write if this is considered.

class Suit(models.IntegerChoices):
    """ All possible card categories in a deck """
    DIAMOND = 1, _("Diamond")
    SPADE = 2, _("Spade")
    HEART = 3, _("Heart")
    CLUB = 4, _("Club")
    
class Choiceful(models.Model):
    # CURRENTLY:
    from_enum_old = models.IntegerField(choices=Suit.choices)
    
    # NEW: raised an fields.E005 prior to proposed PR. Now, retains reference 
    # to class and transparently resolves via implicit `.choices` call
    from_new = models.IntegerField(choices=Suit)

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top