#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.

Reply via email to