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: |                 if isinstance(base, str) and "." in base: | ||||||
|                     base_app_label, base_name = base.split(".", 1) |                     base_app_label, base_name = base.split(".", 1) | ||||||
|                     dependencies.append((base_app_label, base_name, None, True)) |                     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 |             # Depend on the other end of the primary key if it's a relation | ||||||
|             if primary_key_rel: |             if primary_key_rel: | ||||||
|                 dependencies.append(( |                 dependencies.append(( | ||||||
|   | |||||||
| @@ -2454,3 +2454,28 @@ class AutodetectorTests(TestCase): | |||||||
|         self.assertNumberMigrations(changes, 'app', 1) |         self.assertNumberMigrations(changes, 'app', 1) | ||||||
|         self.assertOperationTypes(changes, 'app', 0, ['DeleteModel']) |         self.assertOperationTypes(changes, 'app', 0, ['DeleteModel']) | ||||||
|         self.assertOperationAttributes(changes, 'app', 0, 0, name='Dog') |         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