Fixed #26088 -- Made autodector detect changing proxy model to MTI.

This commit is contained in:
Jon Dufresne 2016-07-12 18:45:17 -07:00 committed by Tim Graham
parent 81963b37a9
commit b84ecaa736
2 changed files with 86 additions and 0 deletions

View File

@ -612,6 +612,20 @@ class MigrationAutodetector(object):
]
)
# Fix relationships if the model changed from a proxy model to a
# concrete model.
if (app_label, model_name) in self.old_proxy_keys:
for related_object in model_opts.related_objects:
self.add_operation(
related_object.related_model._meta.app_label,
operations.AlterField(
model_name=related_object.related_model._meta.object_name,
name=related_object.field.name,
field=related_object.field,
),
dependencies=[(app_label, model_name, None, True)],
)
def generate_created_proxies(self):
"""
Makes CreateModel statements for proxy models.

View File

@ -240,6 +240,7 @@ class AutodetectorTests(TestCase):
}, ("testapp.author", ))
author_proxy_notproxy = ModelState("testapp", "AuthorProxy", [], {}, ("testapp.author", ))
author_proxy_third = ModelState("thirdapp", "AuthorProxy", [], {"proxy": True}, ("testapp.author", ))
author_proxy_third_notproxy = ModelState("thirdapp", "AuthorProxy", [], {}, ("testapp.author", ))
author_proxy_proxy = ModelState("testapp", "AAuthorProxyProxy", [], {"proxy": True}, ("testapp.authorproxy", ))
author_unmanaged = ModelState("testapp", "AuthorUnmanaged", [], {"managed": False}, ("testapp.author", ))
author_unmanaged_managed = ModelState("testapp", "AuthorUnmanaged", [], {}, ("testapp.author", ))
@ -336,6 +337,10 @@ class AutodetectorTests(TestCase):
("author", models.ForeignKey("thirdapp.AuthorProxy", models.CASCADE)),
("title", models.CharField(max_length=200)),
])
book_proxy_proxy_fk = ModelState("otherapp", "Book", [
("id", models.AutoField(primary_key=True)),
("author", models.ForeignKey("testapp.AAuthorProxyProxy", models.CASCADE)),
])
book_migrations_fk = ModelState("otherapp", "Book", [
("id", models.AutoField(primary_key=True)),
("author", models.ForeignKey("migrations.UnmigratedModel", models.CASCADE)),
@ -1291,6 +1296,73 @@ class AutodetectorTests(TestCase):
# The field name the FK on the book model points to
self.assertEqual(changes['otherapp'][0].operations[0].fields[2][1].remote_field.field_name, 'pk_field')
def test_proxy_to_mti_with_fk_to_proxy(self):
# First, test the pk table and field name.
changes = self.get_changes(
[],
[self.author_empty, self.author_proxy_third, self.book_proxy_fk],
)
self.assertEqual(
changes['otherapp'][0].operations[0].fields[2][1].remote_field.model._meta.db_table,
'testapp_author',
)
self.assertEqual(changes['otherapp'][0].operations[0].fields[2][1].remote_field.field_name, 'id')
# Change AuthorProxy to use MTI.
changes = self.get_changes(
[self.author_empty, self.author_proxy_third, self.book_proxy_fk],
[self.author_empty, self.author_proxy_third_notproxy, self.book_proxy_fk],
)
# Right number/type of migrations for the AuthorProxy model?
self.assertNumberMigrations(changes, 'thirdapp', 1)
self.assertOperationTypes(changes, 'thirdapp', 0, ['DeleteModel', 'CreateModel'])
# Right number/type of migrations for the Book model with a FK to
# AuthorProxy?
self.assertNumberMigrations(changes, 'otherapp', 1)
self.assertOperationTypes(changes, 'otherapp', 0, ['AlterField'])
# otherapp should depend on thirdapp.
self.assertMigrationDependencies(changes, 'otherapp', 0, [('thirdapp', 'auto_1')])
# Now, test the pk table and field name.
self.assertEqual(
changes['otherapp'][0].operations[0].field.remote_field.model._meta.db_table,
'thirdapp_authorproxy',
)
self.assertEqual(changes['otherapp'][0].operations[0].field.remote_field.field_name, 'author_ptr')
def test_proxy_to_mti_with_fk_to_proxy_proxy(self):
# First, test the pk table and field name.
changes = self.get_changes(
[],
[self.author_empty, self.author_proxy, self.author_proxy_proxy, self.book_proxy_proxy_fk],
)
self.assertEqual(
changes['otherapp'][0].operations[0].fields[1][1].remote_field.model._meta.db_table,
'testapp_author',
)
self.assertEqual(changes['otherapp'][0].operations[0].fields[1][1].remote_field.field_name, 'id')
# Change AuthorProxy to use MTI. FK still points to AAuthorProxyProxy,
# a proxy of AuthorProxy.
changes = self.get_changes(
[self.author_empty, self.author_proxy, self.author_proxy_proxy, self.book_proxy_proxy_fk],
[self.author_empty, self.author_proxy_notproxy, self.author_proxy_proxy, self.book_proxy_proxy_fk],
)
# Right number/type of migrations for the AuthorProxy model?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ['DeleteModel', 'CreateModel'])
# Right number/type of migrations for the Book model with a FK to
# AAuthorProxyProxy?
self.assertNumberMigrations(changes, 'otherapp', 1)
self.assertOperationTypes(changes, 'otherapp', 0, ['AlterField'])
# otherapp should depend on testapp.
self.assertMigrationDependencies(changes, 'otherapp', 0, [('testapp', 'auto_1')])
# Now, test the pk table and field name.
self.assertEqual(
changes['otherapp'][0].operations[0].field.remote_field.model._meta.db_table,
'testapp_authorproxy',
)
self.assertEqual(changes['otherapp'][0].operations[0].field.remote_field.field_name, 'author_ptr')
def test_unmanaged_create(self):
"""Tests that the autodetector correctly deals with managed models."""
# First, we test adding an unmanaged model