I have a field in my models.py that accepts choices determined in a class:
from apps.users.constants import UserChoices class User(models.Model): choices = models.CharField(max_length=10, blank=True, choices=UserChoices.choices(), default=UserChoices.PUBLIC_USER)
The choice class is this:
from django.utils.translation import ugettext_lazy as _ class UserChoices: PRIVATE_USER = "private_user" PUBLIC_USER = "public_user" @classmethod def choices(cls): return ( (cls.PRIVATE_USER, _("Private User")), (cls.PUBLIC_USER, _("Public User")), )
My doubt is how can I inherit this UserChoices class to another choice class, in order to extend it with another options.
I tried the following:
class ExtendedChoices(UserChoices): OTHER_CHOICE = "other_choice" @classmethod def choices(cls): return ( UserChoices.choices(), (cls.OTHER_CHOICE, _("Other choice")), )
But it gives me a migration error:
users.OtherModel.other_choice: (fields.E005) 'choices' must be an iterable containing (actual value, human readable name) tuples.
Obviously this example is simplified, the actual code has 40+ choices on the original class and 20+ in the extended one.
Advertisement
Answer
You need to unpack the ones from the parent. You do that with an asterisk (*
):
class ExtendedChoices(UserChoices): OTHER_CHOICE = "other_choice" @classmethod def choices(cls): return ( *UserChoices.choices(), # ← an asterisk to unpack the tuple (cls.OTHER_CHOICE, _("Other choice")), )
If we unpack a tuple in another tuple, we construct a tuple that contains all the items of the unpacked tuple as elements of the new tuple. For example:
>>> x = (1,4,2) >>> (x, 5) ((1, 4, 2), 5) >>> (*x, 5) (1, 4, 2, 5)
If we thus do not use an asterisk, it will simply see x
as a tuple, and we thus construct a 2-tuple with as first element the tuple x
.
If we unpack the first tuple, we obtain a 4-tuple where the first three elements originate from x
followed by 5
.