Opened 6 months ago

Last modified 3 months ago

#28056 assigned Bug

Reverse migration for model rename with cross-app ForeignKey fails

Reported by: Paul Tiplady Owned by:
Component: Migrations Version: 1.10
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

When attempting to reverse a migration for the rename of a model, where the model has ForeignKey references to it from models in other apps, the reverse migration fails with the following error:

ValueError: The field <foreignkey_field> was declared with a lazy reference to '<old_model_name>', but app 'one' doesn't provide model '<old_model_name>'

I've put a simple repro up on github here: https://github.com/paultiplady/django-migration-bug, but here's an outline of the problem:

With two apps, one and two, and the models:

one/models.py:

from django.db import models


class Rename1(models.Model):
    pass

two/models.py:

from django.db import models


class Related2(models.Model):
    rename1 = models.ForeignKey('one.Rename1')

Renaming Rename1 to Rename2 produces a simple migration:

0002_auto_20170408_1617.py:

class Migration(migrations.Migration):

    dependencies = [
        ('one', '0001_initial'),
    ]

    operations = [
        migrations.RenameModel(
            old_name='Rename1',
            new_name='Rename2',
        ),
    ]

But when this migration is reversed, the error is raised:

ValueError: The field two.Related2.rename1 was declared with a lazy reference to 'one.rename1', but app 'one' doesn't provide model 'rename1'.

It's unclear from the error message how I'd even go about attempting to address this problem, and the docs don't mention anything about handling this case (as far as I can tell).

Expected behaviour is to be able to handle this reverse-rename seamlessly, or at least provide a sensible error message if this operation is unsupported.

Naively it looks like the problem is that the two.Related2 model has not been given its own migration when its ForeignKey was changed from one.Rename1 to one.Rename2, instead that change is tracked implicitly and incorrectly in the RenameModel step.

Change History (5)

comment:1 Changed 6 months ago by Gaurav Sehgal

Owner: changed from nobody to Gaurav Sehgal
Status: newassigned

comment:2 Changed 6 months ago by Tim Graham

Triage Stage: UnreviewedAccepted

I think the problem is in ForeignKey.db_type(). It uses self.target_field which is using the state of the current model files rather than migration's state.

comment:3 Changed 5 months ago by Gaurav Sehgal

Can't we have a different migration for rename1 as alterfield, so that its migration's state handled properly.

comment:4 Changed 5 months ago by Gaurav Sehgal

Has patch: set

comment:6 Changed 3 months ago by Tim Graham

Patch needs improvement: set

As described on the pull request, based on my testing, the patch doesn't solve the issue.

Note: See TracTickets for help on using tickets.
Back to Top