#24849: Broken squashmigration when model related to another one gets deleted
----------------------------+------------------------------------
Reporter: riklaunim | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.8
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+------------------------------------
Old description:
> I've got a simple example of an broken squashmigration I had in two apps.
> The problem is that if a model gets deleted, that has relation to other
> model then the squash will crash as something will want to do some
> operation on the non-existing model (relation presence is essential,
> tested on postgres):
>
> Initial:
> {{{
> class Category(models.Model):
> title = models.CharField(max_length=100)
>
> class News(models.Model):
> title = models.CharField(max_length=100)
> category = models.ForeignKey(Category)
> }}}
>
> Second migration:
>
> {{{
> class Category(models.Model):
> title = models.CharField(max_length=100)
>
> class NewCategory(models.Model):
> title = models.CharField(max_length=100)
>
> class News(models.Model):
> title = models.CharField(max_length=100)
> category = models.ForeignKey(NewCategory, blank=True, null=True)
> new_category = models.ForeignKey(NewCategory, blank=True, null=True)
> }}}
>
> Third:
>
> {{{
> class NewCategory(models.Model):
> title = models.CharField(max_length=100)
>
> class News(models.Model):
> title = models.CharField(max_length=100)
> new_category = models.ForeignKey(NewCategory, blank=True, null=True)
> }}}
>
> Squash looks like so:
> {{{
> operations = [
> migrations.CreateModel(
> name='Category',
> fields=[
> ('id', models.AutoField(auto_created=True,
> primary_key=True, serialize=False, verbose_name='ID')),
> ('title', models.CharField(max_length=100)),
> ],
> ),
> migrations.CreateModel(
> name='News',
> fields=[
> ('id', models.AutoField(auto_created=True,
> primary_key=True, serialize=False, verbose_name='ID')),
> ('title', models.CharField(max_length=100)),
> ('category', models.ForeignKey(blank=True,
> to='relateddeleted.Category', null=True)),
> ],
> ),
> migrations.CreateModel(
> name='NewCategory',
> fields=[
> ('id', models.AutoField(auto_created=True,
> primary_key=True, serialize=False, verbose_name='ID')),
> ('title', models.CharField(max_length=100)),
> ],
> ),
> migrations.AddField(
> model_name='news',
> name='new_category',
> field=models.ForeignKey(blank=True,
> to='relateddeleted.NewCategory', null=True),
> ),
> migrations.RemoveField(
> model_name='news',
> name='category',
> ),
> migrations.DeleteModel(
> name='Category',
> ),
> ]
> }}}
>
> And on a clean database it throws:
> {{{
> Applying
> relateddeleted.0001_squashed_0003_auto_20150524_2020...Traceback (most
> recent call last):
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/utils.py", line 64, in execute
> return self.cursor.execute(sql, params)
> psycopg2.ProgrammingError: relation "relateddeleted_category" does not
> exist
>
> The above exception was the direct cause of the following exception:
>
> Traceback (most recent call last):
> File "manage.py", line 10, in <module>
> execute_from_command_line(sys.argv)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/__init__.py", line 338, in
> execute_from_command_line
> utility.execute()
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/__init__.py", line 330, in execute
> self.fetch_command(subcommand).run_from_argv(self.argv)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/commands/test.py", line 30, in
> run_from_argv
> super(Command, self).run_from_argv(argv)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/base.py", line 390, in run_from_argv
> self.execute(*args, **cmd_options)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/commands/test.py", line 74, in execute
> super(Command, self).execute(*args, **options)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/base.py", line 441, in execute
> output = self.handle(*args, **options)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/commands/test.py", line 90, in handle
> failures = test_runner.run_tests(test_labels)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/test/runner.py", line 210, in run_tests
> old_config = self.setup_databases()
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/test/runner.py", line 166, in setup_databases
> **kwargs
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/test/runner.py", line 370, in setup_databases
> serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE",
> True),
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/base/creation.py", line 368, in
> create_test_db
> test_flush=not keepdb,
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/__init__.py", line 120, in call_command
> return command.execute(*args, **defaults)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/base.py", line 441, in execute
> output = self.handle(*args, **options)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/core/management/commands/migrate.py", line 221, in handle
> executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/migrations/executor.py", line 110, in migrate
> self.apply_migration(states[migration], migration, fake=fake,
> fake_initial=fake_initial)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/migrations/executor.py", line 147, in apply_migration
> state = migration.apply(state, schema_editor)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/base/schema.py", line 91, in __exit__
> self.execute(sql)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/base/schema.py", line 111, in execute
> cursor.execute(sql, params)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/utils.py", line 64, in execute
> return self.cursor.execute(sql, params)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/utils.py", line 97, in __exit__
> six.reraise(dj_exc_type, dj_exc_value, traceback)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/utils/six.py", line 658, in reraise
> raise value.with_traceback(tb)
> File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
> packages/django/db/backends/utils.py", line 64, in execute
> return self.cursor.execute(sql, params)
> django.db.utils.ProgrammingError: relation "relateddeleted_category" does
> not exist
> }}}
New description:
I've got a simple example of an broken squashmigration I had in two apps.
The problem is that if a model gets deleted, that has relation to other
model then the squash will crash as something will want to do some
operation on the non-existing model (relation presence is essential,
tested on postgres):
Initial:
{{{
class Category(models.Model):
title = models.CharField(max_length=100)
class News(models.Model):
title = models.CharField(max_length=100)
category = models.ForeignKey(Category)
}}}
Second migration:
{{{
class Category(models.Model):
title = models.CharField(max_length=100)
class NewCategory(models.Model):
title = models.CharField(max_length=100)
class News(models.Model):
title = models.CharField(max_length=100)
category = models.ForeignKey(Category, blank=True, null=True)
new_category = models.ForeignKey(NewCategory, blank=True, null=True)
}}}
Third:
{{{
class NewCategory(models.Model):
title = models.CharField(max_length=100)
class News(models.Model):
title = models.CharField(max_length=100)
new_category = models.ForeignKey(NewCategory, blank=True, null=True)
}}}
Squash looks like so:
{{{
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='News',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
('category', models.ForeignKey(blank=True,
to='relateddeleted.Category', null=True)),
],
),
migrations.CreateModel(
name='NewCategory',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100)),
],
),
migrations.AddField(
model_name='news',
name='new_category',
field=models.ForeignKey(blank=True,
to='relateddeleted.NewCategory', null=True),
),
migrations.RemoveField(
model_name='news',
name='category',
),
migrations.DeleteModel(
name='Category',
),
]
}}}
And on a clean database it throws:
{{{
Applying
relateddeleted.0001_squashed_0003_auto_20150524_2020...Traceback (most
recent call last):
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: relation "relateddeleted_category" does not
exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/__init__.py", line 338, in
execute_from_command_line
utility.execute()
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/__init__.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/commands/test.py", line 30, in
run_from_argv
super(Command, self).run_from_argv(argv)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/base.py", line 390, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/commands/test.py", line 74, in execute
super(Command, self).execute(*args, **options)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/base.py", line 441, in execute
output = self.handle(*args, **options)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/commands/test.py", line 90, in handle
failures = test_runner.run_tests(test_labels)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/test/runner.py", line 210, in run_tests
old_config = self.setup_databases()
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/test/runner.py", line 166, in setup_databases
**kwargs
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/test/runner.py", line 370, in setup_databases
serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE",
True),
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/base/creation.py", line 368, in create_test_db
test_flush=not keepdb,
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/__init__.py", line 120, in call_command
return command.execute(*args, **defaults)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/base.py", line 441, in execute
output = self.handle(*args, **options)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/core/management/commands/migrate.py", line 221, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/migrations/executor.py", line 110, in migrate
self.apply_migration(states[migration], migration, fake=fake,
fake_initial=fake_initial)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/migrations/executor.py", line 147, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/base/schema.py", line 91, in __exit__
self.execute(sql)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/base/schema.py", line 111, in execute
cursor.execute(sql, params)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/utils.py", line 97, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/utils/six.py", line 658, in reraise
raise value.with_traceback(tb)
File "/home/piotr/devel/envs/migracje/lib/python3.4/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "relateddeleted_category" does
not exist
}}}
--
Comment (by timgraham):
There was a typo in the "Second migration" step in the description:
`category = models.ForeignKey(NewCategory, ...` instead of
`ForeignKey(Category ...`. I fixed that and can now reproduce the same
traceback you reported as of a76309f007fff6957f39190b06f8a9055f73130f
(Django 1.10.dev).
--
Ticket URL: <https://code.djangoproject.com/ticket/24849#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.90e93bda7e86c60154f4174dbeb8ac0a%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.