summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorDavid Wobrock <david.wobrock@gmail.com>2021-10-16 11:20:33 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-10-25 10:45:35 +0200
commitea00a0843eb7a7bb074625a663ca4f5c86b8c5bd (patch)
treeb3fb925bf40e5ace19eefa8dc09941e60054e2b7 /django
parentc9ebe4ca4e3f5d5d76bfbdae489e3f44e32416e5 (diff)
[4.0.x] Fixed #31503 -- Made autodetector remove unique/index_together before altering fields.
Backport of 0314593fe8e7dc685bbb6585eee40e755588864e from main
Diffstat (limited to 'django')
-rw-r--r--django/db/migrations/autodetector.py53
1 files changed, 46 insertions, 7 deletions
diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py
index 594658ce99..96cb463848 100644
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -178,8 +178,12 @@ class MigrationAutodetector:
# Generate index removal operations before field is removed
self.generate_removed_constraints()
self.generate_removed_indexes()
- # Generate field operations
+ # Generate field renaming operations.
self.generate_renamed_fields()
+ # Generate removal of foo together.
+ self.generate_removed_altered_unique_together()
+ self.generate_removed_altered_index_together()
+ # Generate field operations.
self.generate_removed_fields()
self.generate_added_fields()
self.generate_altered_fields()
@@ -1105,8 +1109,7 @@ class MigrationAutodetector:
dependencies.append((through_app_label, through_object_name, None, True))
return dependencies
- def _generate_altered_foo_together(self, operation):
- option_name = operation.option_name
+ def _get_altered_foo_together_operations(self, option_name):
for app_label, model_name in sorted(self.kept_model_keys):
old_model_name = self.renamed_models.get((app_label, model_name), model_name)
old_model_state = self.from_state.models[app_label, old_model_name]
@@ -1134,13 +1137,49 @@ class MigrationAutodetector:
dependencies.extend(self._get_dependencies_for_foreign_key(
app_label, model_name, field, self.to_state,
))
+ yield (
+ old_value,
+ new_value,
+ app_label,
+ model_name,
+ dependencies,
+ )
+ def _generate_removed_altered_foo_together(self, operation):
+ for (
+ old_value,
+ new_value,
+ app_label,
+ model_name,
+ dependencies,
+ ) in self._get_altered_foo_together_operations(operation.option_name):
+ removal_value = new_value.intersection(old_value)
+ if removal_value or old_value:
self.add_operation(
app_label,
- operation(
- name=model_name,
- **{option_name: new_value}
- ),
+ operation(name=model_name, **{operation.option_name: removal_value}),
+ dependencies=dependencies,
+ )
+
+ def generate_removed_altered_unique_together(self):
+ self._generate_removed_altered_foo_together(operations.AlterUniqueTogether)
+
+ def generate_removed_altered_index_together(self):
+ self._generate_removed_altered_foo_together(operations.AlterIndexTogether)
+
+ def _generate_altered_foo_together(self, operation):
+ for (
+ old_value,
+ new_value,
+ app_label,
+ model_name,
+ dependencies,
+ ) in self._get_altered_foo_together_operations(operation.option_name):
+ removal_value = new_value.intersection(old_value)
+ if new_value != removal_value:
+ self.add_operation(
+ app_label,
+ operation(name=model_name, **{operation.option_name: new_value}),
dependencies=dependencies,
)