mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #23091: CreateModel and AddField were clashing with deferred SQL
This commit is contained in:
		| @@ -546,6 +546,7 @@ class BaseDatabaseSchemaEditor(object): | ||||
|                     } | ||||
|                 ) | ||||
|         # Drop any FK constraints, we'll remake them later | ||||
|         fks_dropped = set() | ||||
|         if old_field.rel: | ||||
|             fk_names = self._constraint_names(model, [old_field.column], foreign_key=True) | ||||
|             if strict and len(fk_names) != 1: | ||||
| @@ -555,6 +556,7 @@ class BaseDatabaseSchemaEditor(object): | ||||
|                     old_field.column, | ||||
|                 )) | ||||
|             for fk_name in fk_names: | ||||
|                 fks_dropped.add((old_field.column,)) | ||||
|                 self.execute( | ||||
|                     self.sql_delete_fk % { | ||||
|                         "table": self.quote_name(model._meta.db_table), | ||||
| @@ -737,7 +739,7 @@ class BaseDatabaseSchemaEditor(object): | ||||
|                 } | ||||
|             ) | ||||
|         # Does it have a foreign key? | ||||
|         if new_field.rel: | ||||
|         if new_field.rel and fks_dropped: | ||||
|             to_table = new_field.rel.to._meta.db_table | ||||
|             to_column = new_field.rel.get_related_field().column | ||||
|             self.execute( | ||||
|   | ||||
| @@ -1051,6 +1051,33 @@ class OperationTests(OperationTestBase): | ||||
|             operation.database_backwards("test_alorwrtto", editor, new_state, project_state) | ||||
|         self.assertColumnNotExists("test_alorwrtto_rider", "_order") | ||||
|  | ||||
|     def test_alter_fk(self): | ||||
|         """ | ||||
|         Tests that creating and then altering an FK works correctly | ||||
|         and deals with the pending SQL (#23091) | ||||
|         """ | ||||
|         project_state = self.set_up_test_model("test_alfk") | ||||
|         # Test adding and then altering the FK in one go | ||||
|         create_operation = migrations.CreateModel( | ||||
|             name="Rider", | ||||
|             fields=[ | ||||
|                 ("id", models.AutoField(primary_key=True)), | ||||
|                 ("pony", models.ForeignKey(to="Pony")), | ||||
|             ], | ||||
|         ) | ||||
|         create_state = project_state.clone() | ||||
|         create_operation.state_forwards("test_alfk", create_state) | ||||
|         alter_operation = migrations.AlterField( | ||||
|             model_name='Rider', | ||||
|             name='pony', | ||||
|             field=models.ForeignKey(editable=False, to="Pony"), | ||||
|         ) | ||||
|         alter_state = create_state.clone() | ||||
|         alter_operation.state_forwards("test_alfk", alter_state) | ||||
|         with connection.schema_editor() as editor: | ||||
|             create_operation.database_forwards("test_alfk", editor, project_state, create_state) | ||||
|             alter_operation.database_forwards("test_alfk", editor, create_state, alter_state) | ||||
|  | ||||
|     @unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse") | ||||
|     def test_run_sql(self): | ||||
|         """ | ||||
|   | ||||
| @@ -331,6 +331,48 @@ class SchemaTests(TransactionTestCase): | ||||
|         self.assertEqual(columns['name'][0], "TextField") | ||||
|         self.assertEqual(bool(columns['name'][1][6]), False) | ||||
|  | ||||
|     @unittest.skipUnless(connection.features.supports_foreign_keys, "No FK support") | ||||
|     def test_alter_fk(self): | ||||
|         """ | ||||
|         Tests altering of FKs | ||||
|         """ | ||||
|         # Create the table | ||||
|         with connection.schema_editor() as editor: | ||||
|             editor.create_model(Author) | ||||
|             editor.create_model(Book) | ||||
|         # Ensure the field is right to begin with | ||||
|         columns = self.column_classes(Book) | ||||
|         self.assertEqual(columns['author_id'][0], "IntegerField") | ||||
|         # Make sure the FK constraint is present | ||||
|         constraints = self.get_constraints(Book._meta.db_table) | ||||
|         for name, details in constraints.items(): | ||||
|             if details['columns'] == ["author_id"] and details['foreign_key']: | ||||
|                 self.assertEqual(details['foreign_key'], ('schema_author', 'id')) | ||||
|                 break | ||||
|         else: | ||||
|             self.fail("No FK constraint for author_id found") | ||||
|         # Alter the FK | ||||
|         new_field = ForeignKey(Author, editable=False) | ||||
|         new_field.set_attributes_from_name("author") | ||||
|         with connection.schema_editor() as editor: | ||||
|             editor.alter_field( | ||||
|                 Book, | ||||
|                 Book._meta.get_field_by_name("author")[0], | ||||
|                 new_field, | ||||
|                 strict=True, | ||||
|             ) | ||||
|         # Ensure the field is right afterwards | ||||
|         columns = self.column_classes(Book) | ||||
|         self.assertEqual(columns['author_id'][0], "IntegerField") | ||||
|         # Make sure the FK constraint is present | ||||
|         constraints = self.get_constraints(Book._meta.db_table) | ||||
|         for name, details in constraints.items(): | ||||
|             if details['columns'] == ["author_id"] and details['foreign_key']: | ||||
|                 self.assertEqual(details['foreign_key'], ('schema_author', 'id')) | ||||
|                 break | ||||
|         else: | ||||
|             self.fail("No FK constraint for author_id found") | ||||
|  | ||||
|     def test_rename(self): | ||||
|         """ | ||||
|         Tests simple altering of fields | ||||
|   | ||||
		Reference in New Issue
	
	Block a user