mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[3.1.x] Fixed #31416 -- Made autodetector find dependencies for MTI model creation on base fields removal.
Removing a base field must take place before adding a new inherited
model that has a field with the same name.
Backport of 33c365781a from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							ccf3cecbaf
						
					
				
				
					commit
					114da2d045
				
			| @@ -563,6 +563,16 @@ class MigrationAutodetector: | ||||
|                 if isinstance(base, str) and "." in base: | ||||
|                     base_app_label, base_name = base.split(".", 1) | ||||
|                     dependencies.append((base_app_label, base_name, None, True)) | ||||
|                     # Depend on the removal of base fields if the new model has | ||||
|                     # a field with the same name. | ||||
|                     old_base_model_state = self.from_state.models.get((base_app_label, base_name)) | ||||
|                     new_base_model_state = self.to_state.models.get((base_app_label, base_name)) | ||||
|                     if old_base_model_state and new_base_model_state: | ||||
|                         removed_base_fields = set(old_base_model_state.fields).difference( | ||||
|                             new_base_model_state.fields, | ||||
|                         ).intersection(model_state.fields) | ||||
|                         for removed_base_field in removed_base_fields: | ||||
|                             dependencies.append((base_app_label, base_name, removed_base_field, False)) | ||||
|             # Depend on the other end of the primary key if it's a relation | ||||
|             if primary_key_rel: | ||||
|                 dependencies.append(( | ||||
|   | ||||
| @@ -2454,3 +2454,28 @@ class AutodetectorTests(TestCase): | ||||
|         self.assertNumberMigrations(changes, 'app', 1) | ||||
|         self.assertOperationTypes(changes, 'app', 0, ['DeleteModel']) | ||||
|         self.assertOperationAttributes(changes, 'app', 0, 0, name='Dog') | ||||
|  | ||||
|     def test_add_model_with_field_removed_from_base_model(self): | ||||
|         """ | ||||
|         Removing a base field takes place before adding a new inherited model | ||||
|         that has a field with the same name. | ||||
|         """ | ||||
|         before = [ | ||||
|             ModelState('app', 'readable', [ | ||||
|                 ('id', models.AutoField(primary_key=True)), | ||||
|                 ('title', models.CharField(max_length=200)), | ||||
|             ]), | ||||
|         ] | ||||
|         after = [ | ||||
|             ModelState('app', 'readable', [ | ||||
|                 ('id', models.AutoField(primary_key=True)), | ||||
|             ]), | ||||
|             ModelState('app', 'book', [ | ||||
|                 ('title', models.CharField(max_length=200)), | ||||
|             ], bases=('app.readable',)), | ||||
|         ] | ||||
|         changes = self.get_changes(before, after) | ||||
|         self.assertNumberMigrations(changes, 'app', 1) | ||||
|         self.assertOperationTypes(changes, 'app', 0, ['RemoveField', 'CreateModel']) | ||||
|         self.assertOperationAttributes(changes, 'app', 0, 0, name='title', model_name='readable') | ||||
|         self.assertOperationAttributes(changes, 'app', 0, 1, name='book') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user