Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Should choice values be enumeration instances? #126

bckohan started this conversation in Ideas
Discussion options

Impacted attributes: Field.flatchoices and Field.choices.

Motivation: #123

This would mostly be about removing the hash equivalency requirement on enum types for 100% interface compatibility. The only known thing in core this fixes is the list display in the admin for non-hash equivalent Enum types.

Would need to also consider how this would affect migrations.

I expect this would have a lot of breaking impacts in other parts of the code, so right now my null is that we should not do this. It does warrant more investigation though on the 3.0 timeline.

You must be logged in to vote

Replies: 3 comments

Comment options

(Continuing the discussion from #123)

From my viewpoint, the only reason to want to advise enum instances to be hash equivalent to their values is because Django choose completely the wrong architecture for their Choices.

It has annoyed me to no end that their TextChoices etc do not just subclass Enum. Why do I think it's the wrong architecture: They were basically trying to make a three-valued Enum (name, value, display_value/key) versus the standard two-valued Enum (name, value). Principally, for display in eg the Admin interface one should encode at most a display_key in the code and use the I18n mechanism to generate the display_value from that. I thus don't even get why they thought they'd need something beyond an Enum. The most logical display_key would be <enum_class_name>..

Their admin interface handles the third value by using a dict internally to translate the Enum value into the display_value/key and(!) they use the raw value of the field and not the Python value for it, or your methods would've worked by specifying choices as Enum_instance <-> display value. From this comes the need for the raw value in the field to be hash equivalent to the enum instance.

Now, given that Django will not be changing this, the question is whether it is correct to advise hash-equivalency. I actually think it is flat out wrong, because it very much suggests (but not guarantees) that if values are hash equivalent, they'd also return equals = True. And that is just not the intent of using a pure Enum, where the Enum instance is not at all equivalent to their value.

You suggested that switching to choices being Enum_instance <-> display value would cause trouble with (de)serialization all over the place. But I don't follow you on that. If you know something is an Enum, the obvious way to (de)serialize is Enum.value for the one way and Enum(value) for the other way. Nothing in there says anything about requirements on hashes. It might be worthwhile to check what eg. Pydantic is doing but I would be surprised if it requires in anyway some specific thing about hashes.

So, I conclude that the correct choice is choices being Enum_instance <-> display value. However, this is the conclusion in the perfect world, the ivory tower etc. Practically speaking I must confess that I have no clue what problems this change would be causing.

I did suggest to only re-implement flatchoices and leave choices alone as a way to mitigate the risk of the change as from a first glance I gathered that flatchoices is only used for display purposes. It might be that the whole choices tuple is only used for display purposes (/validation of acceptable values) though in which case it might even be feasible to provide choices as Enum_instance <-> display value.

I want to finish with stating that I'm just a passer-by. I'm very happy with your library and I don't mind implementing any of the work-arounds listed in #123. I do not have to do the work of making the change etc so in the end you have to make the choice that is not just right for this library but for you as a maintainer.

You must be logged in to vote
0 replies
Comment options

bckohan
May 2, 2025
Maintainer Author

Moved this to a discussion so it doesn't get buried in the issues.

Thanks for this! Your perspective is very helpful. Especially because I'm considering which ideas from this lib might be worth trying to push back into core.

A few points:

  • 100% agree on TextChoices/IntegerChoices design flaws. They were in-part the motivation for this lib. Some (but certainly not all) of the awkwardness is downstream from understandable migration complexities. Migration files should only ever have plain old data types in them.
  • The test suite is robust enough that I can make this change in one location and then just see what breaks. Maybe it'll just work! My goal was maximum compatibility which I'd assumed to be best achieved by making EnumFields look to the rest of the ecosystem to be an interface compatible superset to a normal field with choices. The goal wasn't just compatibility with core but also with other third party packages that have been written to work with fields with choices.
  • You might be interested in enum-properties if you want a TextChoices/IntegerChoices like interface that inherits enum.Enum, is typed and provides an arbitrary number of additional properties beyond just label.
  • Hash equivalency/equality is provided out of the box by stdlib StrEnum, IntEnum types. This gave me some confidence in the recommendation, but I respect the philosophical difference of opinion!
  • My hesitation with just overriding flatchoices is that other libraries or applications might be using it in a way that may break if I do (which is why this change would have to bump the major version).
You must be logged in to vote
0 replies
Comment options

Fair point about the other libraries built on top of Django which may or may not have made assumptions about the contents of choices. I also had forgotten about the migrations files as a possible problem.

I don't really want the TextChoices, I just want to use an Enum and have it work out of the box with Django 😀 . As I said, the obvious translation key for an Enum is class_name.value and it should not be possible or needed to define the display values when defining the field - that can be done in the translation files for I18n and if those are not provided, the enum name is good enough as a display value.

I've got some more problems with Django though, like the help text on the model fields. Ugh, mixing UI with database interface - parts of your code that should be as far apart from each other as possible. And then having it generate a new migration because you changed the help text... Or the whole ModelListView etc - tying UI directly to your database model. But let's not get started on all of those, I do understand that the makers of Django prioritize different things than I do.

The fact that StrEnum and IntEnum are hash equivalent is just a (happy?) side effect. Given that especially StrEnum has only been added very recently I'd say the case for using pure Enums should still be strong and forcing hash equivalency on them is not obvious.

The best solution by far is that the requirement in Django for hash equivalency is removed, which I do think is reachable, given it only shows up in the admin interface (although I did understand that that is one of the more hackish modules to Django). The choice whether to try and support pure Enums in the admin interface out of the box for your library is something I can't help you with to decide. I will be bowing out of the discussion as I don't feel that I have more to contribute and I'm not certain at all that I'm sufficiently realistic in my views.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
enhancement New feature or request question Further information is requested BREAKING A change that is not backwards compatible.
Converted from issue

This discussion was converted from issue #124 on May 02, 2025 16:28.

AltStyle によって変換されたページ (->オリジナル) /