mirror of https://github.com/django/django.git
Fixed #26710 -- Made CreateModel.references_model() take app_label into account.
This commit is contained in:
parent
316395d828
commit
7fc4c1db62
|
@ -104,20 +104,22 @@ class CreateModel(ModelOperation):
|
||||||
return "Create %smodel %s" % ("proxy " if self.options.get("proxy", False) else "", self.name)
|
return "Create %smodel %s" % ("proxy " if self.options.get("proxy", False) else "", self.name)
|
||||||
|
|
||||||
def references_model(self, name, app_label=None):
|
def references_model(self, name, app_label=None):
|
||||||
strings_to_check = [self.name]
|
name_lower = name.lower()
|
||||||
|
if name_lower == self.name_lower:
|
||||||
|
return True
|
||||||
|
|
||||||
# Check we didn't inherit from the model
|
# Check we didn't inherit from the model
|
||||||
for base in self.bases:
|
models_to_check = [base for base in self.bases if base is not models.Model]
|
||||||
if isinstance(base, six.string_types):
|
|
||||||
strings_to_check.append(base.split(".")[-1])
|
|
||||||
# Check we have no FKs/M2Ms with it
|
# Check we have no FKs/M2Ms with it
|
||||||
for fname, field in self.fields:
|
for fname, field in self.fields:
|
||||||
if field.remote_field:
|
if field.remote_field:
|
||||||
if isinstance(field.remote_field.model, six.string_types):
|
models_to_check.append(field.remote_field.model)
|
||||||
strings_to_check.append(field.remote_field.model.split(".")[-1])
|
# Now go over all the models and check against them
|
||||||
# Now go over all the strings and compare them
|
for model in models_to_check:
|
||||||
for string in strings_to_check:
|
model_app_label, model_name = self.model_to_key(model)
|
||||||
if string.lower() == name.lower():
|
if model_name.lower() == name_lower:
|
||||||
return True
|
if app_label is None or not model_app_label or model_app_label == app_label:
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def model_to_key(self, model):
|
def model_to_key(self, model):
|
||||||
|
|
|
@ -13,15 +13,15 @@ class OptimizerTests(SimpleTestCase):
|
||||||
Tests the migration autodetector.
|
Tests the migration autodetector.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def optimize(self, operations):
|
def optimize(self, operations, app_label):
|
||||||
"""
|
"""
|
||||||
Handy shortcut for getting results + number of loops
|
Handy shortcut for getting results + number of loops
|
||||||
"""
|
"""
|
||||||
optimizer = MigrationOptimizer()
|
optimizer = MigrationOptimizer()
|
||||||
return optimizer.optimize(operations), optimizer._iterations
|
return optimizer.optimize(operations, app_label), optimizer._iterations
|
||||||
|
|
||||||
def assertOptimizesTo(self, operations, expected, exact=None, less_than=None):
|
def assertOptimizesTo(self, operations, expected, exact=None, less_than=None, app_label=None):
|
||||||
result, iterations = self.optimize(operations)
|
result, iterations = self.optimize(operations, app_label)
|
||||||
result = [repr(f.deconstruct()) for f in result]
|
result = [repr(f.deconstruct()) for f in result]
|
||||||
expected = [repr(f.deconstruct()) for f in expected]
|
expected = [repr(f.deconstruct()) for f in expected]
|
||||||
self.assertEqual(expected, result)
|
self.assertEqual(expected, result)
|
||||||
|
@ -34,8 +34,8 @@ class OptimizerTests(SimpleTestCase):
|
||||||
"Optimization did not take less than %s iterations (it took %s)" % (less_than, iterations)
|
"Optimization did not take less than %s iterations (it took %s)" % (less_than, iterations)
|
||||||
)
|
)
|
||||||
|
|
||||||
def assertDoesNotOptimize(self, operations):
|
def assertDoesNotOptimize(self, operations, **kwargs):
|
||||||
self.assertOptimizesTo(operations, operations)
|
self.assertOptimizesTo(operations, operations, **kwargs)
|
||||||
|
|
||||||
def test_single(self):
|
def test_single(self):
|
||||||
"""
|
"""
|
||||||
|
@ -212,6 +212,29 @@ class OptimizerTests(SimpleTestCase):
|
||||||
migrations.DeleteModel("Foo"),
|
migrations.DeleteModel("Foo"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
# The same operations should be optimized if app_label is specified and
|
||||||
|
# a FK references a model from the other app.
|
||||||
|
self.assertOptimizesTo(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
|
||||||
|
migrations.DeleteModel("Foo"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
|
||||||
|
],
|
||||||
|
app_label="otherapp",
|
||||||
|
)
|
||||||
|
# But it shouldn't work if a FK references a model with the same
|
||||||
|
# app_label.
|
||||||
|
self.assertDoesNotOptimize(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Bar", [("other", models.ForeignKey("testapp.Foo", models.CASCADE))]),
|
||||||
|
migrations.DeleteModel("Foo"),
|
||||||
|
],
|
||||||
|
app_label="testapp",
|
||||||
|
)
|
||||||
# This should not work - bases should block it
|
# This should not work - bases should block it
|
||||||
self.assertOptimizesTo(
|
self.assertOptimizesTo(
|
||||||
[
|
[
|
||||||
|
@ -225,6 +248,28 @@ class OptimizerTests(SimpleTestCase):
|
||||||
migrations.DeleteModel("Foo"),
|
migrations.DeleteModel("Foo"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
# The same operations should be optimized if app_label and none of
|
||||||
|
# bases belong to that app.
|
||||||
|
self.assertOptimizesTo(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo", )),
|
||||||
|
migrations.DeleteModel("Foo"),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo", )),
|
||||||
|
],
|
||||||
|
app_label="otherapp",
|
||||||
|
)
|
||||||
|
# But it shouldn't work if some of bases belongs to the specified app.
|
||||||
|
self.assertDoesNotOptimize(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Bar", [("size", models.IntegerField())], bases=("testapp.Foo", )),
|
||||||
|
migrations.DeleteModel("Foo"),
|
||||||
|
],
|
||||||
|
app_label="testapp",
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_model_add_field(self):
|
def test_create_model_add_field(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue