[Django] #27764: Running migration that deletes child model (in multi-table inheritance) backwards results in an error

32 views
Skip to first unread message

Django

unread,
Jan 23, 2017, 7:42:26 AM1/23/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
------------------------------------------------+------------------------
Reporter: Alexandru Mărășteanu | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------------+------------------------
1. Create two models where one of them inherits the other:
{{{
class Foo(models.Model):
test = models.CharField(max_length=256)


class Bar(Foo):
pass
}}}

2. Generate and run migrations.

`migrations/0001_initial.py` is:
{{{
...
operations = [
migrations.CreateModel(
name='Foo',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('test', models.CharField(max_length=256)),
],
),
migrations.CreateModel(
name='Bar',
fields=[
('foo_ptr', models.OneToOneField(auto_created=True,
on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='foo.Foo')),
],
bases=('foo.foo',),
),
]
...
}}}

3. Delete the child model (`Bar`)

4. Generate and run migrations again.

`migrations/0002_auto_20170123_1212.py` is:
{{{
...
migrations.RemoveField(
model_name='bar',
name='foo_ptr',
),
migrations.DeleteModel(
name='Bar',
),
...
}}}

5. Run migrations backwards (i.e. `python migrate APP zero`)
{{{
django.db.utils.ProgrammingError: column "foo_ptr_id" of relation
"foo_bar" already exists
}}}

Verified with Django (1.9.6, 1.9.12 and 1.10.5) and psycopg2 (2.5.2) on
macOS 10.12.2 with Python 2.7.12, PostgreSQL 9.5.4.

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

Django

unread,
Jan 23, 2017, 7:46:56 AM1/23/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: nobody
Mărășteanu |

Type: Bug | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:

Keywords: | 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 Alexandru Mărășteanu:

Old description:

New description:


class Bar(Foo):
pass
}}}

5. Run migrations backwards
{{{
$ python manage.py migrate foo zero
Operations to perform:
Unapply all migrations: foo
Running migrations:
Rendering model states... DONE
Unapplying foo.0002_auto_20170123_1212...Traceback (most recent call
last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/core/management/__init__.py", line 367, in
execute_from_command_line
utility.execute()
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/core/management/__init__.py", line 359, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/core/management/base.py", line 294, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/core/management/base.py", line 345, in execute
output = self.handle(*args, **options)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/core/management/commands/migrate.py", line 204, in handle
fake_initial=fake_initial,
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 119, in migrate
state = self._migrate_all_backwards(plan, full_plan, fake=fake)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 194, in
_migrate_all_backwards
self.unapply_migration(states[migration], migration, fake=fake)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 264, in unapply_migration
state = migration.unapply(state, schema_editor)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/migrations/migration.py", line 178, in unapply
operation.database_backwards(self.app_label, schema_editor,
from_state, to_state)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/migrations/operations/fields.py", line 153, in
database_backwards
schema_editor.add_field(from_model,
to_model._meta.get_field(self.name))
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/postgresql/schema.py", line 21, in add_field
super(DatabaseSchemaEditor, self).add_field(model, field)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/base/schema.py", line 409, in add_field
self.execute(sql, params)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/base/schema.py", line 112, in execute
cursor.execute(sql, params)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/alexei/.virtualenvs/djbug/lib/python2.7/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)


django.db.utils.ProgrammingError: column "foo_ptr_id" of relation
"foo_bar" already exists
}}}

Verified with Django (1.9.6, 1.9.12 and 1.10.5) and psycopg2 (2.5.2) on
macOS 10.12.2 with Python 2.7.12, PostgreSQL 9.5.4.

--

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

Django

unread,
Jan 23, 2017, 7:58:52 AM1/23/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: nobody
Mărășteanu |
Type: Bug | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:

Keywords: | 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 Alexandru Mărășteanu:

Old description:

> 1. Create two models where one of them inherits the other:

> django.db.utils.ProgrammingError: column "foo_ptr_id" of relation
> "foo_bar" already exists
> }}}
>
> Verified with Django (1.9.6, 1.9.12 and 1.10.5) and psycopg2 (2.5.2) on
> macOS 10.12.2 with Python 2.7.12, PostgreSQL 9.5.4.

New description:


class Bar(Foo):
pass
}}}

5. Run migrations backwards


{{{
$ python manage.py migrate foo zero
Operations to perform:
Unapply all migrations: foo
Running migrations:
Rendering model states... DONE
Unapplying foo.0002_auto_20170123_1212...Traceback (most recent call
last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)

File "/djbug/lib/python2.7/site-


packages/django/core/management/__init__.py", line 367, in
execute_from_command_line
utility.execute()

File "/djbug/lib/python2.7/site-


packages/django/core/management/__init__.py", line 359, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)

File "/djbug/lib/python2.7/site-


packages/django/core/management/base.py", line 294, in run_from_argv
self.execute(*args, **cmd_options)

File "/djbug/lib/python2.7/site-


packages/django/core/management/base.py", line 345, in execute
output = self.handle(*args, **options)

File "/djbug/lib/python2.7/site-


packages/django/core/management/commands/migrate.py", line 204, in handle
fake_initial=fake_initial,

File "/djbug/lib/python2.7/site-


packages/django/db/migrations/executor.py", line 119, in migrate
state = self._migrate_all_backwards(plan, full_plan, fake=fake)

File "/djbug/lib/python2.7/site-


packages/django/db/migrations/executor.py", line 194, in
_migrate_all_backwards
self.unapply_migration(states[migration], migration, fake=fake)

File "/djbug/lib/python2.7/site-


packages/django/db/migrations/executor.py", line 264, in unapply_migration
state = migration.unapply(state, schema_editor)

File "/djbug/lib/python2.7/site-


packages/django/db/migrations/migration.py", line 178, in unapply
operation.database_backwards(self.app_label, schema_editor,
from_state, to_state)

File "/djbug/lib/python2.7/site-


packages/django/db/migrations/operations/fields.py", line 153, in
database_backwards
schema_editor.add_field(from_model,
to_model._meta.get_field(self.name))

File "/djbug/lib/python2.7/site-


packages/django/db/backends/postgresql/schema.py", line 21, in add_field
super(DatabaseSchemaEditor, self).add_field(model, field)

File "/djbug/lib/python2.7/site-


packages/django/db/backends/base/schema.py", line 409, in add_field
self.execute(sql, params)

File "/djbug/lib/python2.7/site-


packages/django/db/backends/base/schema.py", line 112, in execute
cursor.execute(sql, params)

File "/djbug/lib/python2.7/site-packages/django/db/backends/utils.py",


line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)

File "/djbug/lib/python2.7/site-packages/django/db/backends/utils.py",


line 64, in execute
return self.cursor.execute(sql, params)

File "/djbug/lib/python2.7/site-packages/django/db/utils.py", line 94,


in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/djbug/lib/python2.7/site-packages/django/db/backends/utils.py",


line 64, in execute
return self.cursor.execute(sql, params)

django.db.utils.ProgrammingError: column "foo_ptr_id" of relation
"foo_bar" already exists
}}}

Verified with Django (1.9.6, 1.9.12 and 1.10.5) and psycopg2 (2.5.2) on
macOS 10.12.2 with Python 2.7.12, PostgreSQL 9.5.4.

--

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

Django

unread,
Jan 24, 2017, 6:52:45 PM1/24/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: nobody
Mărășteanu |
Type: Bug | Status: closed
Component: Migrations | Version: 1.10
Severity: Normal | Resolution: duplicate

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

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


Comment:

I think this is a duplicate of #24424 (presumably that ticket will also
verify that the backwards operations also work). If the `RemoveField`
operation is omitted by the autodetector, then this seems to work.

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

Django

unread,
Jan 26, 2017, 4:59:11 AM1/26/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: nobody
Mărășteanu |
Type: Bug | Status: new
Component: Migrations | Version: 1.10
Severity: Normal | Resolution:

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Alexandru Mărășteanu):

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


Comment:

I don't think it's related to #24424 My guess is the operations
`[RemoveField, DeleteModel]`, when run in reverse, will generate
`[CreateModel, AddField]` so what happens is the `AddField` there is
redundant, hence the error. Again, the error appears not when you run the
migration forward (i.e. to delete the model), but when you run it backward
(i.e. to re-create the model).

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

Django

unread,
Jan 26, 2017, 5:05:21 AM1/26/17
to django-...@googlegroups.com
#27764: Running migration that deletes child model (in multi-table inheritance)
backwards results in an error
-------------------------------------+-------------------------------------
Reporter: Alexandru | Owner: nobody
Mărășteanu |
Type: Bug | Status: closed
Component: Migrations | Version: 1.10
Severity: Normal | Resolution: duplicate

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Alexandru Mărășteanu):

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


Comment:

I don't seem to be able to delete my previous comment. Please disregard
it.

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

Reply all
Reply to author
Forward
0 new messages