`Enum` already enforces that no 2 instances may have the same value, but
by default, it allows 2 or more attributes to refer to that same instance.
I believe that is desirable to allow situations like the following:
{{{
class Vehicle(models.TextChoices):
CAR = 'C'
TRUCK = 'T'
JET_SKI = 'J'
DEFAULT = 'C'
}}}
With `enum.unique()` ''not'' enforced, this will create 3 entries (not 4)
and make the single `CAR` entry instance available through either
`Vehicle.CAR` or `Vehicle.DEFAULT`. By enforcing `enum.unique()`, we cause
an exception to be raised at `DEFAULT = 'C'` instead of making an alias to
`Vehicle.CAR`, and that appears to be purely a limitation and not a
benefit.
--
Ticket URL: <https://code.djangoproject.com/ticket/30920>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* cc: Shai Berger, Nick Pope (added)
* type: Bug => New feature
* resolution: => wontfix
Comment:
Thanks for this report, however I don't think that it's the desired
behavior. All properties (`.names`, `.labels`, `.choices`, `.names` ) will
return only the first value without enforcing uniqueness, for example:
{{{
class Fruit(models.IntegerChoices):
APPLE = 1, 'Apple'
PINEAPPLE = 1, 'Pineapple'
DEFAULT 1
>>> Fruit.choices
[(1, 'Apple')]
>>> Fruit.labels
['Apple']
>>> Fruit.values
[1]
>>> Fruit.names
['APPLE']
}}}
What can be confusing. We made few design decisions to create the most
usable and less error-prone classes for defining choices, IMO. `Choices`
is not a strict `enum` implementation.
--
Ticket URL: <https://code.djangoproject.com/ticket/30920#comment:1>
Comment (by Steve Jorgensen):
Makes sense. Thanks for explaining the decision in your response, @felixxm
--
Ticket URL: <https://code.djangoproject.com/ticket/30920#comment:2>
Comment (by Nick Pope):
Hi Steve,
As Felix says, we're using enums under the hood, but we've added some
additional constraints on top.
These helper classes are intended to make working with field choices
easier and more structured.
I see the following problems with allowing duplicate values:
1. It is most likely not intended, e.g. a copy-paste error.
2. Where we use display labels, it may be unclear that multiple entries
refer to the same value.
3. Following your example, when we load the value back from the database,
is it "Default" or "Car"?
This is why we decided to enforce unique values. There is nothing to stop
someone from doing things as they did before, i.e. not using `Choices`.
For your example of a default case, I'd suggest that the blank value is
the default, e.g. set `__empty__ = _('(Default)')`.
That way you can change the default easily without needing to make a new
migration.
Alternatively, if you need to enforce the value in the database, you can
just set it in `clean()` on your form or as the `Field.default`.
I hope that helps.
--
Ticket URL: <https://code.djangoproject.com/ticket/30920#comment:3>