Refs #27064 -- Made migrations generate RenameIndex operations when renaming Meta.indexes.
This commit is contained in:
parent
11310e9abb
commit
c6cec3c2d2
|
@ -179,6 +179,7 @@ class MigrationAutodetector:
|
||||||
self.generate_removed_indexes()
|
self.generate_removed_indexes()
|
||||||
# Generate field renaming operations.
|
# Generate field renaming operations.
|
||||||
self.generate_renamed_fields()
|
self.generate_renamed_fields()
|
||||||
|
self.generate_renamed_indexes()
|
||||||
# Generate removal of foo together.
|
# Generate removal of foo together.
|
||||||
self.generate_removed_altered_unique_together()
|
self.generate_removed_altered_unique_together()
|
||||||
self.generate_removed_altered_index_together()
|
self.generate_removed_altered_index_together()
|
||||||
|
@ -1187,14 +1188,41 @@ class MigrationAutodetector:
|
||||||
|
|
||||||
old_indexes = old_model_state.options[option_name]
|
old_indexes = old_model_state.options[option_name]
|
||||||
new_indexes = new_model_state.options[option_name]
|
new_indexes = new_model_state.options[option_name]
|
||||||
add_idx = [idx for idx in new_indexes if idx not in old_indexes]
|
added_indexes = [idx for idx in new_indexes if idx not in old_indexes]
|
||||||
rem_idx = [idx for idx in old_indexes if idx not in new_indexes]
|
removed_indexes = [idx for idx in old_indexes if idx not in new_indexes]
|
||||||
|
renamed_indexes = []
|
||||||
|
# Find renamed indexes.
|
||||||
|
remove_from_added = []
|
||||||
|
remove_from_removed = []
|
||||||
|
for new_index in added_indexes:
|
||||||
|
new_index_dec = new_index.deconstruct()
|
||||||
|
new_index_name = new_index_dec[2].pop("name")
|
||||||
|
for old_index in removed_indexes:
|
||||||
|
old_index_dec = old_index.deconstruct()
|
||||||
|
old_index_name = old_index_dec[2].pop("name")
|
||||||
|
# Indexes are the same except for the names.
|
||||||
|
if (
|
||||||
|
new_index_dec == old_index_dec
|
||||||
|
and new_index_name != old_index_name
|
||||||
|
):
|
||||||
|
renamed_indexes.append((old_index_name, new_index_name, None))
|
||||||
|
remove_from_added.append(new_index)
|
||||||
|
remove_from_removed.append(old_index)
|
||||||
|
# Remove renamed indexes from the lists of added and removed
|
||||||
|
# indexes.
|
||||||
|
added_indexes = [
|
||||||
|
idx for idx in added_indexes if idx not in remove_from_added
|
||||||
|
]
|
||||||
|
removed_indexes = [
|
||||||
|
idx for idx in removed_indexes if idx not in remove_from_removed
|
||||||
|
]
|
||||||
|
|
||||||
self.altered_indexes.update(
|
self.altered_indexes.update(
|
||||||
{
|
{
|
||||||
(app_label, model_name): {
|
(app_label, model_name): {
|
||||||
"added_indexes": add_idx,
|
"added_indexes": added_indexes,
|
||||||
"removed_indexes": rem_idx,
|
"removed_indexes": removed_indexes,
|
||||||
|
"renamed_indexes": renamed_indexes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1221,6 +1249,21 @@ class MigrationAutodetector:
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def generate_renamed_indexes(self):
|
||||||
|
for (app_label, model_name), alt_indexes in self.altered_indexes.items():
|
||||||
|
for old_index_name, new_index_name, old_fields in alt_indexes[
|
||||||
|
"renamed_indexes"
|
||||||
|
]:
|
||||||
|
self.add_operation(
|
||||||
|
app_label,
|
||||||
|
operations.RenameIndex(
|
||||||
|
model_name=model_name,
|
||||||
|
new_name=new_index_name,
|
||||||
|
old_name=old_index_name,
|
||||||
|
old_fields=old_fields,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def create_altered_constraints(self):
|
def create_altered_constraints(self):
|
||||||
option_name = operations.AddConstraint.option_name
|
option_name = operations.AddConstraint.option_name
|
||||||
for app_label, model_name in sorted(self.kept_model_keys):
|
for app_label, model_name in sorted(self.kept_model_keys):
|
||||||
|
|
|
@ -350,6 +350,11 @@ Migrations
|
||||||
:attr:`Meta.indexes <django.db.models.Options.indexes>` or
|
:attr:`Meta.indexes <django.db.models.Options.indexes>` or
|
||||||
:attr:`~django.db.models.Options.index_together` options.
|
:attr:`~django.db.models.Options.index_together` options.
|
||||||
|
|
||||||
|
* The migrations autodetector now generates
|
||||||
|
:class:`~django.db.migrations.operations.RenameIndex` operations instead of
|
||||||
|
``RemoveIndex`` and ``AddIndex``, when renaming indexes defined in the
|
||||||
|
:attr:`Meta.indexes <django.db.models.Options.indexes>`.
|
||||||
|
|
||||||
Models
|
Models
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -2565,6 +2565,39 @@ class AutodetectorTests(TestCase):
|
||||||
changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
|
changes, "otherapp", 0, 0, model_name="book", name="book_title_author_idx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_rename_indexes(self):
|
||||||
|
book_renamed_indexes = ModelState(
|
||||||
|
"otherapp",
|
||||||
|
"Book",
|
||||||
|
[
|
||||||
|
("id", models.AutoField(primary_key=True)),
|
||||||
|
("author", models.ForeignKey("testapp.Author", models.CASCADE)),
|
||||||
|
("title", models.CharField(max_length=200)),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"indexes": [
|
||||||
|
models.Index(
|
||||||
|
fields=["author", "title"], name="renamed_book_title_author_idx"
|
||||||
|
)
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
changes = self.get_changes(
|
||||||
|
[self.author_empty, self.book_indexes],
|
||||||
|
[self.author_empty, book_renamed_indexes],
|
||||||
|
)
|
||||||
|
self.assertNumberMigrations(changes, "otherapp", 1)
|
||||||
|
self.assertOperationTypes(changes, "otherapp", 0, ["RenameIndex"])
|
||||||
|
self.assertOperationAttributes(
|
||||||
|
changes,
|
||||||
|
"otherapp",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
model_name="book",
|
||||||
|
new_name="renamed_book_title_author_idx",
|
||||||
|
old_name="book_title_author_idx",
|
||||||
|
)
|
||||||
|
|
||||||
def test_order_fields_indexes(self):
|
def test_order_fields_indexes(self):
|
||||||
"""Test change detection of reordering of fields in indexes."""
|
"""Test change detection of reordering of fields in indexes."""
|
||||||
changes = self.get_changes(
|
changes = self.get_changes(
|
||||||
|
|
Loading…
Reference in New Issue