Opened 11 years ago
Last modified 11 years ago
#23956 closed Bug
makemigrations creates broken initial migration for models with multiple inheritance — at Version 2
| Reported by: | Kirill Gagarski | Owned by: | nobody |
|---|---|---|---|
| Component: | Migrations | Version: | 1.7 |
| Severity: | Normal | Keywords: | migrations inheritance |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Hello.
I am trying to create models that use multiple inheritance and then use django migrations mechanism to migrate. But I have some problems with it.
I have created simplest example to reproduce.
Steps to reproduce
- Create a
migrationstestdjango app with followingmodels.py:
from django.db import models
class A(models.Model):
a_id = models.IntegerField(primary_key=True)
class B(models.Model):
b_id = models.IntegerField(primary_key=True)
class C(A, B):
pass
class D(A, B):
pass
class E(A, B):
pass
- run './manage.py makemigrations migrationstest'
- run './manage.py migrate migrationstest'
Expected results
Fine migration
Actual results
Exception is thrown while running 'migrate':
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/core/management/commands/migrate.py", line 160, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/migrations/executor.py", line 63, in migrate
self.apply_migration(migration, fake=fake)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/migrations/executor.py", line 97, in apply_migration
migration.apply(project_state, schema_editor)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/migrations/migration.py", line 107, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/migrations/operations/fields.py", line 37, in database_forwards
field,
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/backends/schema.py", line 390, in add_field
self.execute(sql, params)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/backends/schema.py", line 99, in execute
cursor.execute(sql, params)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/backends/utils.py", line 81, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/utils/six.py", line 549, in reraise
raise value.with_traceback(tb)
File "/home/gagarski/polyana-web/environment/lib/python3.4/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column "b_ptr_id" of relation "migrationstest_d" already exists
More details
The generated initial migration:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='A',
fields=[
('a_id', models.IntegerField(serialize=False, primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='B',
fields=[
('b_id', models.IntegerField(serialize=False, primary_key=True)),
],
options={
},
bases=(models.Model,),
),
migrations.CreateModel(
name='C',
fields=[
('a_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, to='migrationstest.A', auto_created=True)),
],
options={
},
bases=('migrationstest.a', 'migrationstest.b'),
),
migrations.CreateModel(
name='D',
fields=[
('a_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, to='migrationstest.A', auto_created=True)),
],
options={
},
bases=('migrationstest.a', 'migrationstest.b'),
),
migrations.CreateModel(
name='E',
fields=[
('a_ptr', models.OneToOneField(parent_link=True, serialize=False, primary_key=True, to='migrationstest.A', auto_created=True)),
('b_ptr', models.OneToOneField(parent_link=True, to='migrationstest.B', auto_created=True)),
],
options={
},
bases=('migrationstest.a', 'migrationstest.b'),
),
migrations.AddField(
model_name='d',
name='b_ptr',
field=models.OneToOneField(parent_link=True, to='migrationstest.B', auto_created=True),
preserve_default=True,
),
migrations.AddField(
model_name='c',
name='b_ptr',
field=models.OneToOneField(parent_link=True, to='migrationstest.B', auto_created=True),
preserve_default=True,
),
]
As you can see b_ptr field is added in CreateModel only for the last model (E).
For D and C it is added via AddField. But it seems that b_ptr is already added to them even without a field specified in CreateModel's fields argument (with the help of bases argument, I think).
Output of sqlmigrate
BEGIN;
CREATE TABLE "migrationstest_a" ("a_id" integer NOT NULL PRIMARY KEY);
CREATE TABLE "migrationstest_b" ("b_id" integer NOT NULL PRIMARY KEY);
CREATE TABLE "migrationstest_c" ("b_ptr_id" integer NOT NULL UNIQUE, "a_ptr_id" integer NOT NULL PRIMARY KEY);
CREATE TABLE "migrationstest_d" ("b_ptr_id" integer NOT NULL UNIQUE, "a_ptr_id" integer NOT NULL PRIMARY KEY);
CREATE TABLE "migrationstest_e" ("b_ptr_id" integer NOT NULL UNIQUE, "a_ptr_id" integer NOT NULL PRIMARY KEY);
ALTER TABLE "migrationstest_d" ADD COLUMN "b_ptr_id" integer NOT NULL UNIQUE;
ALTER TABLE "migrationstest_d" ALTER COLUMN "b_ptr_id" DROP DEFAULT;
ALTER TABLE "migrationstest_c" ADD COLUMN "b_ptr_id" integer NOT NULL UNIQUE;
ALTER TABLE "migrationstest_c" ALTER COLUMN "b_ptr_id" DROP DEFAULT;
ALTER TABLE "migrationstest_c" ADD CONSTRAINT "migrationste_b_ptr_id_6684147e60c05d18_fk_migrationstest_b_b_id" FOREIGN KEY ("b_ptr_id") REFERENCES "migrationstest_b" ("b_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_c" ADD CONSTRAINT "migrationste_a_ptr_id_2670758b3e821055_fk_migrationstest_a_a_id" FOREIGN KEY ("a_ptr_id") REFERENCES "migrationstest_a" ("a_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_d" ADD CONSTRAINT "migrationste_b_ptr_id_2ed6e3025678dfb9_fk_migrationstest_b_b_id" FOREIGN KEY ("b_ptr_id") REFERENCES "migrationstest_b" ("b_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_d" ADD CONSTRAINT "migrationste_a_ptr_id_4d0009d1fad71dec_fk_migrationstest_a_a_id" FOREIGN KEY ("a_ptr_id") REFERENCES "migrationstest_a" ("a_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_e" ADD CONSTRAINT "migrationste_b_ptr_id_29d2159648c59c3e_fk_migrationstest_b_b_id" FOREIGN KEY ("b_ptr_id") REFERENCES "migrationstest_b" ("b_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_e" ADD CONSTRAINT "migrationste_a_ptr_id_405a8eb9707708c9_fk_migrationstest_a_a_id" FOREIGN KEY ("a_ptr_id") REFERENCES "migrationstest_a" ("a_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_d" ADD CONSTRAINT "migrationste_b_ptr_id_2ed6e3025678dfb9_fk_migrationstest_b_b_id" FOREIGN KEY ("b_ptr_id") REFERENCES "migrationstest_b" ("b_id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "migrationstest_c" ADD CONSTRAINT "migrationste_b_ptr_id_6684147e60c05d18_fk_migrationstest_b_b_id" FOREIGN KEY ("b_ptr_id") REFERENCES "migrationstest_b" ("b_id") DEFERRABLE INITIALLY DEFERRED;
COMMIT;
Questions
Is there a good reasons to do like that? Is there a workaround that can help me to use automatic migration generation without manually editing them (at least initial migration)?
Change History (2)
comment:1 by , 11 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 11 years ago
| Description: | modified (diff) |
|---|