Opened 11 years ago
Last modified 11 years ago
#23956 closed Bug
makemigrations creates broken initial migration for models with multiple inheritance — at Initial Version
| 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
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 'migrationstest' django app with following models.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).
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)?