mirror of https://github.com/django/django.git
Fixed #22875: Optimizer did not take through= into account.
This commit is contained in:
parent
f07735c619
commit
b30d32ff24
|
@ -160,6 +160,19 @@ class MigrationOptimizer(object):
|
||||||
return om(operation, other, in_between or [])
|
return om(operation, other, in_between or [])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def model_to_key(self, model):
|
||||||
|
"""
|
||||||
|
Takes either a model class or a "appname.ModelName" string
|
||||||
|
and returns (appname, modelname)
|
||||||
|
"""
|
||||||
|
if isinstance(model, six.string_types):
|
||||||
|
return model.split(".", 1)
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
model._meta.app_label,
|
||||||
|
model._meta.object_name,
|
||||||
|
)
|
||||||
|
|
||||||
def reduce_model_create_delete(self, operation, other, in_between):
|
def reduce_model_create_delete(self, operation, other, in_between):
|
||||||
"""
|
"""
|
||||||
Folds a CreateModel and a DeleteModel into nothing.
|
Folds a CreateModel and a DeleteModel into nothing.
|
||||||
|
@ -206,13 +219,15 @@ class MigrationOptimizer(object):
|
||||||
# Don't allow optimisations of FKs through models they reference
|
# Don't allow optimisations of FKs through models they reference
|
||||||
if hasattr(other.field, "rel") and other.field.rel:
|
if hasattr(other.field, "rel") and other.field.rel:
|
||||||
for between in in_between:
|
for between in in_between:
|
||||||
if isinstance(other.field.rel.to, six.string_types):
|
# Check that it doesn't point to the model
|
||||||
object_name, app_label = other.field.rel.to.split(".", 1)
|
app_label, object_name = self.model_to_key(other.field.rel.to)
|
||||||
else:
|
|
||||||
object_name = other.field.rel.to._meta.object_name
|
|
||||||
app_label = other.field.rel.to._meta.app_label
|
|
||||||
if between.references_model(object_name, app_label):
|
if between.references_model(object_name, app_label):
|
||||||
return None
|
return None
|
||||||
|
# Check that it's not through the model
|
||||||
|
if getattr(other.field.rel, "through", None):
|
||||||
|
app_label, object_name = self.model_to_key(other.field.rel.through)
|
||||||
|
if between.references_model(object_name, app_label):
|
||||||
|
return None
|
||||||
# OK, that's fine
|
# OK, that's fine
|
||||||
return [
|
return [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
|
|
@ -201,6 +201,44 @@ class OptimizerTests(TestCase):
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_create_model_add_field_not_through_fk(self):
|
||||||
|
"""
|
||||||
|
AddField should NOT optimize into CreateModel if it's an FK to a model
|
||||||
|
that's between them.
|
||||||
|
"""
|
||||||
|
self.assertOptimizesTo(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Link", [("url", models.TextField())]),
|
||||||
|
migrations.AddField("Foo", "link", models.ForeignKey("migrations.Link")),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("Link", [("url", models.TextField())]),
|
||||||
|
migrations.AddField("Foo", "link", models.ForeignKey("migrations.Link")),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_model_add_field_not_through_m2m_through(self):
|
||||||
|
"""
|
||||||
|
AddField should NOT optimize into CreateModel if it's an M2M using a
|
||||||
|
through that's created between them.
|
||||||
|
"""
|
||||||
|
# Note: The middle model is not actually a valid through model,
|
||||||
|
# but that doesn't matter, as we never render it.
|
||||||
|
self.assertOptimizesTo(
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("LinkThrough", []),
|
||||||
|
migrations.AddField("Foo", "link", models.ManyToManyField("migrations.Link", through="migrations.LinkThrough")),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
migrations.CreateModel("Foo", [("name", models.CharField(max_length=255))]),
|
||||||
|
migrations.CreateModel("LinkThrough", []),
|
||||||
|
migrations.AddField("Foo", "link", models.ManyToManyField("migrations.Link", through="migrations.LinkThrough")),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_create_model_alter_field(self):
|
def test_create_model_alter_field(self):
|
||||||
"""
|
"""
|
||||||
AlterField should optimize into CreateModel.
|
AlterField should optimize into CreateModel.
|
||||||
|
|
Loading…
Reference in New Issue