mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #34333 -- Fixed migration operations ordering when adding index/constraint on new foreign key.
Thanks Simon Charette and David Wobrock for reviews.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							dde2537fbb
						
					
				
				
					commit
					4b1bfea284
				
			| @@ -1304,6 +1304,7 @@ class MigrationAutodetector: | ||||
|  | ||||
|     def generate_added_indexes(self): | ||||
|         for (app_label, model_name), alt_indexes in self.altered_indexes.items(): | ||||
|             dependencies = self._get_dependencies_for_model(app_label, model_name) | ||||
|             for index in alt_indexes["added_indexes"]: | ||||
|                 self.add_operation( | ||||
|                     app_label, | ||||
| @@ -1311,6 +1312,7 @@ class MigrationAutodetector: | ||||
|                         model_name=model_name, | ||||
|                         index=index, | ||||
|                     ), | ||||
|                     dependencies=dependencies, | ||||
|                 ) | ||||
|  | ||||
|     def generate_removed_indexes(self): | ||||
| @@ -1367,6 +1369,7 @@ class MigrationAutodetector: | ||||
|             app_label, | ||||
|             model_name, | ||||
|         ), alt_constraints in self.altered_constraints.items(): | ||||
|             dependencies = self._get_dependencies_for_model(app_label, model_name) | ||||
|             for constraint in alt_constraints["added_constraints"]: | ||||
|                 self.add_operation( | ||||
|                     app_label, | ||||
| @@ -1374,6 +1377,7 @@ class MigrationAutodetector: | ||||
|                         model_name=model_name, | ||||
|                         constraint=constraint, | ||||
|                     ), | ||||
|                     dependencies=dependencies, | ||||
|                 ) | ||||
|  | ||||
|     def generate_removed_constraints(self): | ||||
| @@ -1425,6 +1429,22 @@ class MigrationAutodetector: | ||||
|             dependencies.append((through_app_label, through_object_name, None, True)) | ||||
|         return dependencies | ||||
|  | ||||
|     def _get_dependencies_for_model(self, app_label, model_name): | ||||
|         """Return foreign key dependencies of the given model.""" | ||||
|         dependencies = [] | ||||
|         model_state = self.to_state.models[app_label, model_name] | ||||
|         for field in model_state.fields.values(): | ||||
|             if field.is_relation: | ||||
|                 dependencies.extend( | ||||
|                     self._get_dependencies_for_foreign_key( | ||||
|                         app_label, | ||||
|                         model_name, | ||||
|                         field, | ||||
|                         self.to_state, | ||||
|                     ) | ||||
|                 ) | ||||
|         return dependencies | ||||
|  | ||||
|     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( | ||||
|   | ||||
| @@ -2720,6 +2720,65 @@ class AutodetectorTests(BaseAutodetectorTests): | ||||
|             changes, "testapp", 0, 0, model_name="author", constraint=added_constraint | ||||
|         ) | ||||
|  | ||||
|     def test_add_constraints_with_new_model(self): | ||||
|         book_with_unique_title_and_pony = ModelState( | ||||
|             "otherapp", | ||||
|             "Book", | ||||
|             [ | ||||
|                 ("id", models.AutoField(primary_key=True)), | ||||
|                 ("title", models.CharField(max_length=200)), | ||||
|                 ("pony", models.ForeignKey("otherapp.Pony", models.CASCADE)), | ||||
|             ], | ||||
|             { | ||||
|                 "constraints": [ | ||||
|                     models.UniqueConstraint( | ||||
|                         fields=["title", "pony"], | ||||
|                         name="unique_title_pony", | ||||
|                     ) | ||||
|                 ] | ||||
|             }, | ||||
|         ) | ||||
|         changes = self.get_changes( | ||||
|             [self.book_with_no_author], | ||||
|             [book_with_unique_title_and_pony, self.other_pony], | ||||
|         ) | ||||
|  | ||||
|         self.assertNumberMigrations(changes, "otherapp", 1) | ||||
|         self.assertOperationTypes( | ||||
|             changes, | ||||
|             "otherapp", | ||||
|             0, | ||||
|             ["CreateModel", "AddField", "AddConstraint"], | ||||
|         ) | ||||
|  | ||||
|     def test_add_index_with_new_model(self): | ||||
|         book_with_index_title_and_pony = ModelState( | ||||
|             "otherapp", | ||||
|             "Book", | ||||
|             [ | ||||
|                 ("id", models.AutoField(primary_key=True)), | ||||
|                 ("title", models.CharField(max_length=200)), | ||||
|                 ("pony", models.ForeignKey("otherapp.Pony", models.CASCADE)), | ||||
|             ], | ||||
|             { | ||||
|                 "indexes": [ | ||||
|                     models.Index(fields=["title", "pony"], name="index_title_pony"), | ||||
|                 ] | ||||
|             }, | ||||
|         ) | ||||
|         changes = self.get_changes( | ||||
|             [self.book_with_no_author], | ||||
|             [book_with_index_title_and_pony, self.other_pony], | ||||
|         ) | ||||
|  | ||||
|         self.assertNumberMigrations(changes, "otherapp", 1) | ||||
|         self.assertOperationTypes( | ||||
|             changes, | ||||
|             "otherapp", | ||||
|             0, | ||||
|             ["CreateModel", "AddField", "AddIndex"], | ||||
|         ) | ||||
|  | ||||
|     def test_remove_constraints(self): | ||||
|         """Test change detection of removed constraints.""" | ||||
|         changes = self.get_changes( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user