To reproduce, create the following as your model:
{{{#!python
class Outer(object):
class Inner(models.CharField):
pass
class A(models.Model):
field = Outer.Inner(max_length=20)
}}}
After running {{{manage.py makemigrations}}}, the generated migrations
file contains the following:
{{{#!python
migrations.CreateModel(
name='A',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('field', test1.models.Inner(max_length=20)),
],
),
}}}
Note the {{{test1.models.Inner}}}, which should have been
{{{test1.models.Outer.Inner}}}.
The real life case involved an EnumField from django-enumfields, defined
as an inner class of a Django Model class, similar to this:
{{{#!python
import enum
from enumfields import Enum, EnumField
class Thing(models.Model):
@enum.unique
class State(Enum):
on = 'on'
off = 'off'
state = EnumField(enum=State)
}}}
This results in the following migrations code:
{{{#!python
migrations.CreateModel(
name='Thing',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('state', enumfields.fields.EnumField(enum=test1.models.State,
max_length=10)),
],
),
}}}
This refers to {{{test1.models.State}}}, instead of to
{{{test1.models.Thing.State}}}.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* type: Uncategorized => Bug
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:1>
* type: Bug => New feature
* version: 1.10 => master
* component: Database layer (models, ORM) => Migrations
* stage: Unreviewed => Accepted
Comment:
This should be possible to do by relying on `__qualname__` (instead of
`__name__`) now that master is Python 3 only.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:2>
* owner: nobody => ChillarAnand
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:3>
* cc: anand21nanda@… (added)
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/8177 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:4>
* needs_better_patch: 0 => 1
Comment:
I think we should focus on using `__qualname__` during migration
serialization as well instead of simply solving the field subclasses case.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:5>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"fb0f987f7de5f01d72c671444df0f95de4706fc6" fb0f987]:
{{{
#!CommitTicketReference repository=""
revision="fb0f987f7de5f01d72c671444df0f95de4706fc6"
Fixed #27914 -- Added support for nested classes in
Field.deconstruct()/__repr__().
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:6>
Comment (by Tim Graham <timograham@…>):
In [changeset:"451b585c2f76507b1be9d855a41cf2bb5aad6026" 451b585]:
{{{
#!CommitTicketReference repository=""
revision="451b585c2f76507b1be9d855a41cf2bb5aad6026"
Refs #27914 -- Used __qualname__ in model operations' deconstruct().
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:7>
Comment (by jcohen28):
I am still encountering this issue when running `makemigrations` on models
that include a django-enumfields EnumField. From tracing through the code,
I believe the Enum is getting serialized using the
django.db.migrations.serializer.TypeSerializer, which still uses the
`__name__` rather than `__qualname__`. As a result, the Enum's path gets
resolved to `app_name.models.enum_name` and the generated migration file
throws an error "app_name.models has no 'enum_name' member". The correct
path for the inner class should be `app_name.models.model_name.enum_name`.
https://github.com/django/django/blob/master/django/db/migrations/serializer.py#L266
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:8>
* status: closed => new
* resolution: fixed =>
Comment:
Reopening it. Will recheck with nested enum field.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:9>
* cc: Hasan Ramezani (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:10>
* status: new => assigned
* owner: ChillarAnand => Hasan Ramezani
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:11>
Comment (by Hasan Ramezani):
[https://github.com/django/django/pull/11858 PR for fixing enum class as
an inner class of model.]
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:12>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"d3030deaaa50b7814e34ef1e71f2afaf97c6bec6" d3030dea]:
{{{
#!CommitTicketReference repository=""
revision="d3030deaaa50b7814e34ef1e71f2afaf97c6bec6"
Refs #27914 -- Moved test enum.Enum subclasses outside of
WriterTests.test_serialize_enums().
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:13>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"6452112640081ac8838147a8ba192c45879203d8" 6452112]:
{{{
#!CommitTicketReference repository=""
revision="6452112640081ac8838147a8ba192c45879203d8"
Refs #27914 -- Fixed serialization of nested enum.Enum classes in
migrations.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:14>
* status: assigned => closed
* resolution: => fixed
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:15>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"1a4db2cc2890e5bac471bb2cb17a50d4c0424525" 1a4db2c]:
{{{
#!CommitTicketReference repository=""
revision="1a4db2cc2890e5bac471bb2cb17a50d4c0424525"
[3.0.x] Refs #27914 -- Moved test enum.Enum subclasses outside of
WriterTests.test_serialize_enums().
Backport of d3030deaaa50b7814e34ef1e71f2afaf97c6bec6 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:16>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"30271a47daefdf46a8383888f5c0f051b31864e6" 30271a47]:
{{{
#!CommitTicketReference repository=""
revision="30271a47daefdf46a8383888f5c0f051b31864e6"
[3.0.x] Refs #27914 -- Fixed serialization of nested enum.Enum classes in
migrations.
Backport of 6452112640081ac8838147a8ba192c45879203d8 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:17>
* status: closed => new
* resolution: fixed =>
Comment:
commit 6452112640081ac8838147a8ba192c45879203d8 does not resolve this
ticket.
The commit patched the `EnumSerializer` with `__qualname__`, which works
for Enum members.
However, the `serializer_factory` is returning `TypeSerializer` for the
Enum subclass, which is still using `__name__`
With v3.0.x introducing models.Choices, models.IntegerChoices, using
nested enums will become a common pattern; serializing them properly
with `__qualname__` seems prudent.
Here's a patch for the 3.0rc1 build
https://github.com/django/django/files/3879265/django_db_migrations_serializer_TypeSerializer.patch.txt
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:18>
* needs_better_patch: 1 => 0
* has_patch: 1 => 0
Comment:
Agreed, we should fix this.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:19>
Comment (by Hasan Ramezani):
I will create a patch a soon as possible.
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:20>
Comment (by John Bowen):
Submitted PR: https://github.com/django/django/pull/12125
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:21>
* Attachment "0001-Fixes-27914-Fixed-serialization-of-nested-classes-
se.patch" added.
PR: https://github.com/django/django/pull/12125
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:22>
* Attachment "0002-Fixed-
WriterTests.test_deconstruct_class_arguments-t.patch" added.
* status: new => closed
* resolution: => fixed
Comment:
In [changeset:"29d8198841ea39af44f3bc835d646e642d498475" 29d8198]:
{{{
#!CommitTicketReference repository=""
revision="29d8198841ea39af44f3bc835d646e642d498475"
Fixed #27914 -- Fixed serialization of nested classes in migrations.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:23>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"b6cbc88f26aa7a4279a71cd8895dc0a1aa6ff398" b6cbc88f]:
{{{
#!CommitTicketReference repository=""
revision="b6cbc88f26aa7a4279a71cd8895dc0a1aa6ff398"
[3.0.x] Fixed #27914 -- Fixed serialization of nested classes in
migrations.
Backport of 29d8198841ea39af44f3bc835d646e642d498475 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27914#comment:24>