Was playing with the choices field (see excerpt below) and trying to put the default=Difficulty.EASY, so that it defaults to EASY when creating an object but the dropdown in the django admin still defaults to VERY_EASY
I took a look at the choices django docs and not sure where I went wrong.
I’ve migrated the changes and restarted the local server, but it didn’t change.
models.py
class Thing(models.Model):
class Difficulty(float, models.Choices):
VERY_EASY = 0.5, "0.5"
EASY = 1, "1"
HARD = 3, "3"
name = models.TextField(max_length=1000)
difficulty = models.FloatField(
choices=Difficulty,
default=Difficulty.EASY,
)
admin.py
from django.contrib import admin
from .models import Thing
admin.site.register(Thing)
Screenshot of difficulty field on brand new Thing object when creating in the django admin

In the terminal, I tried creating a Thing object without setting a difficulty which confirmed that it correctly uses the default (EASY instead of VERY_EASY). So, it seems like just the admin dropdown doesn’t show the default.
terminal
% python manage.py shell
>>> from things.models import Thing
>>> t = Thing.objects.create(name="thingy")
>>> print(t)
thingy
>>> print(t.difficulty)
Difficulty.EASY
>>>
I guess I originally assumed I was doing something wrong with my default in the model but because of the terminal test I’m now wondering: is this a bug?
Thanks as always.
The issue appears to be around using a subclass for the enum rather than one of the default classes.
It also affects user-defined ModelForms as well as the admin-generated form. (In other words, if you create a model form for Thing, you’ll see the same symptoms. As a result, I’m moving this to the Forms category, because it applies to all model forms, not just the admin.)
Anyway, if you change Difficulty to (int, models.Choices) it shows the same symptoms. But, if you change it to (models.IntegerChoices), it works as expected. (Also changing the VERY EASY value to an integer.)
Using a clue I got from ticket #34710, I changed default=Difficulty.EASY to default=Difficulty.EASY.value, and this works as expected with class Difficulty(float, models.Choices)
If I examine the two different classes (Difficulty(models.IntegerChoices) and Difficulty(int, models.Choices)), there are a number of differences.
Most obviously, in the first version, printing Thing.Difficulty.EASY prints 1, but printing Thing.Difficulty.EASY in the second version prints Difficulty.EASY, which shows a difference in the __str__ methods of each. (Both return django.db.models.enums.ChoicesType for type(Thing.Difficulty))
Is this a bug?
(I’m not in a position to know for sure) But it certainly looks like one to me.
Throwing this back out to a wider audience - Anyone else have thoughts on this?
1 Like
I believe this is a bug, as sample from OP is the same as documentation one for a DateField and the documentation also doesn’t use .value when setting the default of a field (see Model field reference | Django documentation | Django ).
The issue is indeed the difference in __str__ representation. The models.IntegerChoices inherit from enum.ReprEnum which makes use of int.__str__ instead of enum.Enum.__str__.
enum.ReprEnum is new in python 3.11, and it was specifically backported in Django 5.2 in django.db.models.enums for python < 3.11. So, I assume the behaviour of using the mixed-in data type for __str__ is intentional (because this is what is used to set the default choice in forms). As a consequence, I think this should not only apply to IntegerChoices or TextChoices, but to all subclasses of models.Choices.
This should be as simple as making models.Choices inherit from enum.ReprEnum instead of enum.Enum.
@StephanieAG : using class Difficulty(float, models.Choices, ReprEnum) (with ReprEnum either imported from python’s enum module if using python >= 3.11 or from Django’s django.db.models.enums if using Django < 6.0 and python < 3.11) would solve the issue.
I’ll file a ticket to Django’s bug tracker.
1 Like
Yep, confirming that importing enum and adding class Difficulty(float, models.Choices, ReprEnum) solved the issue
Thanks for filing a ticket (saw it was #36930 if anyone else is also curious to see it)