[Django] #30774: Migrations uses value of enum object instead of its name

20 views
Skip to first unread message

Django

unread,
Sep 13, 2019, 11:26:34 AM9/13/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name
--------------------------------------+----------------------------------
Reporter: oasl | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 2.2
Severity: Normal | Keywords: Enum, Migrations
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+----------------------------------
When using Enum object as a default value for a CharField, the generated
migration file uses the value of the Enum object instead of the its name.
This causes a problem when using Django translation on the value of the
Enum object.

The problem is that, when the Enum object value get translated to the
users language, the migrations raise an error stating that the Enum does
not have the corresponding value. (because the Enum value is translated to
another language)

Example:

Let say we have this code in models.py:
{{{
from enum import Enum
from django.utils.translation import gettext_lazy as _
from django.db import models


class Status(Enum):
GOOD = _('Good') # 'Good' will be translated
BAD = _('Bad') # 'Bad' will be translated

def __str__(self):
return self.name

class Item(models.Model):
status = models.CharField(default=Status.GOOD, max_length=128)
}}}

In the generated migration file, the code will be:
{{{
...
('status', models.CharField(default=Status('Good'), max_length=128))
...
}}}
After the translation, 'Good' will be translated to another word and it
will not be part of the Status Enum class any more, so the migration file
will raise the error on the previous line:

{{{ValueError: 'Good' is not a valid Status}}}

Shouldn't the code generated by the migration uses the name of the Status
Enum 'GOOD', not the value of it, since it is changeable?

It should be:
{{{
('status', models.CharField(default=Status['GOOD'], max_length=128))
}}}
This will be correct regardless of the translated word

--
Ticket URL: <https://code.djangoproject.com/ticket/30774>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Sep 13, 2019, 1:37:54 PM9/13/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name
----------------------------------+--------------------------------------

Reporter: oasl | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 2.2
Severity: Normal | Resolution:

Keywords: Enum, Migrations | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+--------------------------------------
Description changed by oasl:

Old description:

New description:

When using Enum object as a default value for a CharField, the generated
migration file uses the value of the Enum object instead of the its name.
This causes a problem when using Django translation on the value of the
Enum object.

The problem is that, when the Enum object value get translated to the

users language, the old migration files raise an error stating that the

Example:

def __str__(self):
return self.name

--

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:1>

Django

unread,
Sep 13, 2019, 1:54:59 PM9/13/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
----------------------------------+--------------------------------------
Reporter: oasl | Owner: nobody
Type: Bug | Status: closed
Component: Migrations | Version: master
Severity: Normal | Resolution: needsinfo

Keywords: Enum, Migrations | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+--------------------------------------
Changes (by felixxm):

* status: new => closed
* version: 2.2 => master
* resolution: => needsinfo


Comment:

Thanks for this report, however I'm not sure how translated values can
brake migrations. Can you provide a sample project to reproduce this
issue? Migrations with translatable strings works fine for me:
{{{
>>> class TextEnum(enum.Enum):
... C = _('translatable value')
...
>>> TextEnum(_('translatable value'))
<TextEnum.C: 'translatable value'>
>>> TextEnum('translatable value')
<TextEnum.C: 'translatable value'>
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:2>

Django

unread,
Sep 14, 2019, 12:09:50 PM9/14/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
----------------------------------+--------------------------------------

Reporter: oasl | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: master
Severity: Normal | Resolution:

Keywords: Enum, Migrations | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+--------------------------------------
Changes (by oasl):

* status: closed => new
* resolution: needsinfo =>


Comment:

To experience the bug:

In any Django project, set the default value of a CharField as an enum
object:

{{{
class EnumClass(Enum):
VALUE = _('Value')
}}}
where:
VALUE: is the constant enum object name
'Value': is the translatable enum object value

In the model:
{{{
field = models.CharField(default=EnumClass.VALUE, max_length=128)
}}}

then run: python manage.py makemigrations

In the generated migration file, you will notice that the default value of
the field is set to: EnumClass('Value'), so it calls the enum object by
its value not it is constant name.
run: python manage.py migrate

In the settings.py file:
{{{
LANGUAGE_CODE = 'fr-FR' # set it to any language code other than English
}}}

Run the project after generating, translating, and compiling the messages
file (see: [https://docs.djangoproject.com/en/2.2/topics/i18n/translation
/#message-files message-files])

The project will raise the error: {{{ ValueError: 'Value' is not a valid
EnumClass }}}, on the generated migration file.

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:3>

Django

unread,
Sep 16, 2019, 2:51:03 AM9/16/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
----------------------------------+------------------------------------

Reporter: oasl | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------+------------------------------------
Changes (by felixxm):

* stage: Unreviewed => Accepted


Comment:

This use case looks quite niche for me, i.e. I would expect to store a
unified values (the same for all languages) and translate only labels
visible for users, however I agree that we can fix this.

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:4>

Django

unread,
Sep 16, 2019, 4:07:32 AM9/16/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned

Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Hasan Ramezani):

* status: new => assigned
* owner: nobody => Hasan Ramezani


--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:5>

Django

unread,
Sep 19, 2019, 10:08:58 AM9/19/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Hasan Ramezani):

Here is the diff based on the **@oasl** solution

{{{


Shouldn't the code generated by the migration uses the name of the Status
Enum 'GOOD', not the value of it, since it is changeable?
It should be:
('status', models.CharField(default=Status['GOOD'], max_length=128))
}}}


{{{
diff --git a/django/db/migrations/serializer.py
b/django/db/migrations/serializer.py
index 27b5cbd379..b00c6f0df2 100644
--- a/django/db/migrations/serializer.py
+++ b/django/db/migrations/serializer.py
@@ -120,9 +120,9 @@ class EnumSerializer(BaseSerializer):
def serialize(self):
enum_class = self.value.__class__
module = enum_class.__module__
- v_string, v_imports =
serializer_factory(self.value.value).serialize()
+ _, v_imports = serializer_factory(self.value.value).serialize()
imports = {'import %s' % module, *v_imports}
- return "%s.%s(%s)" % (module, enum_class.__name__, v_string),
imports
+ return "%s.%s['%s']" % (module, enum_class.__name__, self.value),
imports


}}}

@felixxm, what do you think?

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:6>

Django

unread,
Sep 24, 2019, 7:52:14 AM9/24/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

You cannot use a string representation of `self.value` i.e.
`'EnumClass.GOOD'`, IMO we should use a `name` property:
{{{
return "%s.%s[%r]" % (module, enum_class.__name__, self.value.name),
imports
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:7>

Django

unread,
Sep 24, 2019, 6:05:33 PM9/24/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Hasan Ramezani):

* has_patch: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:8>

Django

unread,
Sep 25, 2019, 3:09:11 AM9/25/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 1 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* needs_tests: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:9>

Django

unread,
Sep 25, 2019, 6:33:24 AM9/25/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Hasan Ramezani):

* needs_tests: 1 => 0


--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:10>

Django

unread,
Sep 30, 2019, 4:34:40 AM9/30/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: assigned
Component: Migrations | Version: master
Severity: Normal | Resolution:
Keywords: Enum, Migrations | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* stage: Accepted => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:11>

Django

unread,
Sep 30, 2019, 4:52:57 AM9/30/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: closed
Component: Migrations | Version: master
Severity: Normal | Resolution: fixed

Keywords: Enum, Migrations | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"f0adf3b9b7a19cdee05368ff0c0c2d087f011180" f0adf3b9]:
{{{
#!CommitTicketReference repository=""
revision="f0adf3b9b7a19cdee05368ff0c0c2d087f011180"
Fixed #30774 -- Made serialization in migrations use members names for
Enums.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:12>

Django

unread,
Sep 30, 2019, 4:53:31 AM9/30/19
to django-...@googlegroups.com
#30774: Migrations uses value of enum object instead of its name.
-------------------------------------+-------------------------------------
Reporter: oasl | Owner: Hasan
| Ramezani
Type: Bug | Status: closed
Component: Migrations | Version: master
Severity: Normal | Resolution: fixed
Keywords: Enum, Migrations | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"df0c2ac3586a80a5e37cca3bcb2d4e7ed333d28e" df0c2ac3]:
{{{
#!CommitTicketReference repository=""
revision="df0c2ac3586a80a5e37cca3bcb2d4e7ed333d28e"
[3.0.x] Fixed #30774 -- Made serialization in migrations use members names
for Enums.

Backport of f0adf3b9b7a19cdee05368ff0c0c2d087f011180 from master
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30774#comment:13>

Reply all
Reply to author
Forward
0 new messages