mirror of
https://github.com/django/django.git
synced 2024-11-21 19:09:18 +01:00
Fixed #32263 -- Fixed squashmigrations result with RenameModel on a FK target.
This commit is contained in:
parent
86e13843c2
commit
2b6b6d5754
@ -146,6 +146,9 @@ class Operation:
|
||||
|
||||
return router.allow_migrate_model(connection_alias, model)
|
||||
|
||||
def reduce_related(self, operation, app_label):
|
||||
return None
|
||||
|
||||
def reduce(self, operation, app_label):
|
||||
"""
|
||||
Return either a list of operations the actual operation should be
|
||||
|
@ -134,6 +134,43 @@ class CreateModel(ModelOperation):
|
||||
return True
|
||||
return False
|
||||
|
||||
def reduce_related(self, operation, app_label):
|
||||
if isinstance(operation, RenameModel):
|
||||
impacted_fields = [
|
||||
(_, field)
|
||||
for _, field in self.fields
|
||||
if field.remote_field
|
||||
and field.remote_field.model
|
||||
== f"{app_label}.{operation.old_name_lower}"
|
||||
]
|
||||
if len(impacted_fields) == 0:
|
||||
return [self]
|
||||
|
||||
not_impacted_fields = [
|
||||
(_, field)
|
||||
for (_, field) in self.fields
|
||||
if (_, field) not in impacted_fields
|
||||
]
|
||||
|
||||
fixed_fields = []
|
||||
|
||||
for _, impacted_field in impacted_fields:
|
||||
name, path, args, kwargs = impacted_field.deconstruct()
|
||||
kwargs["to"] = f"{app_label}.{operation.new_name_lower}"
|
||||
impacted_field = impacted_field.__class__(*args, **kwargs)
|
||||
fixed_fields.append((_, impacted_field))
|
||||
|
||||
return [
|
||||
CreateModel(
|
||||
name=self.name,
|
||||
fields=not_impacted_fields + fixed_fields,
|
||||
options=self.options,
|
||||
bases=self.bases,
|
||||
managers=self.managers,
|
||||
),
|
||||
]
|
||||
return super().reduce_related(operation, app_label)
|
||||
|
||||
def reduce(self, operation, app_label):
|
||||
if (
|
||||
isinstance(operation, DeleteModel)
|
||||
|
@ -46,6 +46,7 @@ class MigrationOptimizer:
|
||||
for j, other in enumerate(operations[i + 1 :]):
|
||||
result = operation.reduce(other, app_label)
|
||||
if isinstance(result, list):
|
||||
new_reduced_operations = []
|
||||
in_between = operations[i + 1 : i + j + 1]
|
||||
if right:
|
||||
new_operations.extend(in_between)
|
||||
@ -59,8 +60,13 @@ class MigrationOptimizer:
|
||||
# Otherwise keep trying.
|
||||
new_operations.append(operation)
|
||||
break
|
||||
new_operations.extend(operations[i + j + 2 :])
|
||||
return new_operations
|
||||
|
||||
for _, op in enumerate(new_operations):
|
||||
new_reduced_operations.extend(
|
||||
op.reduce_related(other, app_label) or [op]
|
||||
)
|
||||
new_reduced_operations.extend(operations[i + j + 2 :])
|
||||
return new_reduced_operations
|
||||
elif not result:
|
||||
# Can't perform a right reduction.
|
||||
right = False
|
||||
|
@ -649,6 +649,35 @@ class OptimizerTests(SimpleTestCase):
|
||||
],
|
||||
)
|
||||
|
||||
def test_rename_model_referenced_by_fk(self):
|
||||
self.assertOptimizesTo(
|
||||
[
|
||||
migrations.CreateModel("Author", []),
|
||||
migrations.CreateModel(
|
||||
"Book",
|
||||
[
|
||||
(
|
||||
"author",
|
||||
models.ForeignKey("migrations.author", models.CASCADE),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.RenameModel("Author", "Person"),
|
||||
],
|
||||
[
|
||||
migrations.CreateModel("Person", []),
|
||||
migrations.CreateModel(
|
||||
"Book",
|
||||
[
|
||||
(
|
||||
"author",
|
||||
models.ForeignKey("migrations.person", models.CASCADE),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def test_create_model_alter_field(self):
|
||||
"""
|
||||
AlterField should optimize into CreateModel.
|
||||
|
Loading…
Reference in New Issue
Block a user