Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #23916 -- Allowed makemigrations to handle related model name case changes. #12313

Merged
merged 1 commit into from Mar 25, 2020

Conversation

adamchainz
Copy link
Sponsor Member

@adamchainz adamchainz commented Jan 13, 2020

Ticket

I believe this is the correct fix.

The reason continuous migrations were being generated was the comparison of the before and after deconstructed ForeignKeys in MigrationAutodetector.generate_altered_fields:

if old_field_dec != new_field_dec:

The model name in the migration history is based on the migration that added the model, but nothing ever changes this casing since the autodetector only uses the "model name" (lowercased class name) throughout. ForeignObject.deconstruct() seems to have been a place where this was missed.

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamchainz Thanks 👍 Please add a test for scenario described in the ticket.

@adamchainz
Copy link
Sponsor Member Author

Oh yes ofc

I added the below to the autodetector tests but it already passed before the patch. I think it's because the error wasn't in the autodetector but in the difference between model states / deconstructed fields loaded from migration history and actual models.

    def test_model_case_change(self):
        AuthoR = ModelState('testapp', 'AuthoR', [("id", models.AutoField(primary_key=True))])
        changes = self.get_changes([self.author_empty, self.book], [AuthoR, self.book])
        self.assertNumberMigrations(changes, 'app', 0)

That said, this patch does fix the problem on $clientproject that had the same bug as the ticket.

I will come back to this tomorrow to try add a unit test that does reproduce the scenario.

@adamchainz
Copy link
Sponsor Member Author

I'm finding it too hard to make a replicating test. Tried this as well but it passes on master.

    def test_rename_model_case(self):
        """
        Tests that a model changing case doesn't lead to any autodetected
        operations.
        """
        author1 = ModelState('testapp', 'author', [("id", models.AutoField(primary_key=True))])
        book1 = ModelState("otherapp", "Book", [
            ("id", models.AutoField(primary_key=True)),
            ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
        ])
        author2 = ModelState('testapp', 'Author', [("id", models.AutoField(primary_key=True))])
        book2 = ModelState("otherapp", "Book", [
            ("id", models.AutoField(primary_key=True)),
            ("author", models.ForeignKey("testapp.Author", models.CASCADE)),
        ])
        changes = self.get_changes([author1, book1], [author2, book2])
        self.assertNumberMigrations(changes, 'app', 0)

🤷‍♂

@felixxm
Copy link
Member

felixxm commented Jan 15, 2020

I'm finding it too hard to make a replicating test. Tried this as well but it passes on master.

I will play with this.

@felixxm
Copy link
Member

felixxm commented Jan 16, 2020

@MarkusH Can you take a look? At first glance, I would expect to get two operations: RenameModel and AlterField 🤔 , but with this PR we ignore case changes.

Copy link
Member

@MarkusH MarkusH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. The only concern I have is what implications this change has on existing migration files. Will the change trigger the generation of new migrations?

tests/field_deconstruction/tests.py Outdated Show resolved Hide resolved
@adamchainz
Copy link
Sponsor Member Author

Verified it won't trigger the generation of new migrations with a test project: https://github.com/adamchainz/django-23916 .

@charettes
Copy link
Member

charettes commented Mar 22, 2020

Is the only thing blocking the merge of this change a valid regression test? If it's the case I could likely build one from a simplified scenario.

@felixxm
Copy link
Member

felixxm commented Mar 22, 2020

@charettes Yes, a regression test is missing.

@adamchainz
Copy link
Sponsor Member Author

Took another pass. Found a way to fix up my above test to fail on master and pass on this PR. Mostly it was my call to assertNumberMigrations using the wrong app label(s) 🤦‍♂️

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamchainz Thanks 👍 I pushed small edits.

django/db/models/fields/related.py Outdated Show resolved Hide resolved
tests/migrations/test_autodetector.py Show resolved Hide resolved
@felixxm felixxm changed the title Fixed #23916 -- Made ForeignObject.deconstruct() use lowercase model name Fixed #23916 -- Made autodetector ignore related model name case changes. Mar 25, 2020
@felixxm felixxm changed the title Fixed #23916 -- Made autodetector ignore related model name case changes. Fixed #23916 -- Allowed makemigrations to handle related model name case changes. Mar 25, 2020
@adamchainz
Copy link
Sponsor Member Author

Great, LGTM

…ase changes.

Made autodetector ignore related model name case changes so unnecessary
migrations are not created.
@felixxm felixxm merged commit 9e1b6b8 into django:master Mar 25, 2020
@adamchainz adamchainz deleted the ticket_23916 branch July 20, 2020 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants