mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.10.x] Fixed #26881 -- Fixed duplicate managers in migrations.
When both parent and child models had managers with the same name and
a migrations opt-in both were added to the migration state.
Backport of dab83e5ba1 from master
			
			
This commit is contained in:
		| @@ -446,12 +446,19 @@ class ModelState(object): | |||||||
|             bases = (models.Model,) |             bases = (models.Model,) | ||||||
|  |  | ||||||
|         managers = [] |         managers = [] | ||||||
|  |         manager_names = set() | ||||||
|         default_manager_shim = None |         default_manager_shim = None | ||||||
|         for manager in model._meta.managers: |         for manager in model._meta.managers: | ||||||
|             if manager.use_in_migrations: |             manager_name = force_text(manager.name) | ||||||
|  |             if manager_name in manager_names: | ||||||
|  |                 # Skip overridden managers. | ||||||
|  |                 continue | ||||||
|  |             elif manager.use_in_migrations: | ||||||
|  |                 # Copy managers usable in migrations. | ||||||
|                 new_manager = copy.copy(manager) |                 new_manager = copy.copy(manager) | ||||||
|                 new_manager._set_creation_counter() |                 new_manager._set_creation_counter() | ||||||
|             elif manager is model._base_manager or manager is model._default_manager: |             elif manager is model._base_manager or manager is model._default_manager: | ||||||
|  |                 # Shim custom managers used as default and base managers. | ||||||
|                 new_manager = models.Manager() |                 new_manager = models.Manager() | ||||||
|                 new_manager.model = manager.model |                 new_manager.model = manager.model | ||||||
|                 new_manager.name = manager.name |                 new_manager.name = manager.name | ||||||
| @@ -459,7 +466,8 @@ class ModelState(object): | |||||||
|                     default_manager_shim = new_manager |                     default_manager_shim = new_manager | ||||||
|             else: |             else: | ||||||
|                 continue |                 continue | ||||||
|             managers.append((force_text(manager.name), new_manager)) |             manager_names.add(manager_name) | ||||||
|  |             managers.append((manager_name, new_manager)) | ||||||
|  |  | ||||||
|         # Ignore a shimmed default manager called objects if it's the only one. |         # Ignore a shimmed default manager called objects if it's the only one. | ||||||
|         if managers == [('objects', default_manager_shim)]: |         if managers == [('objects', default_manager_shim)]: | ||||||
|   | |||||||
| @@ -210,6 +210,37 @@ class StateTests(SimpleTestCase): | |||||||
|         author_state = project_state.models['migrations', 'author'] |         author_state = project_state.models['migrations', 'author'] | ||||||
|         self.assertEqual(author_state.managers, []) |         self.assertEqual(author_state.managers, []) | ||||||
|  |  | ||||||
|  |     def test_no_duplicate_managers(self): | ||||||
|  |         """ | ||||||
|  |         When a manager is added with `use_in_migrations = True` and a parent | ||||||
|  |         model had a manager with the same name and `use_in_migrations = True`, | ||||||
|  |         the parent's manager shouldn't appear in the model state (#26881). | ||||||
|  |         """ | ||||||
|  |         new_apps = Apps(['migrations']) | ||||||
|  |  | ||||||
|  |         class PersonManager(models.Manager): | ||||||
|  |             use_in_migrations = True | ||||||
|  |  | ||||||
|  |         class Person(models.Model): | ||||||
|  |             objects = PersonManager() | ||||||
|  |  | ||||||
|  |             class Meta: | ||||||
|  |                 abstract = True | ||||||
|  |  | ||||||
|  |         class BossManager(PersonManager): | ||||||
|  |             use_in_migrations = True | ||||||
|  |  | ||||||
|  |         class Boss(Person): | ||||||
|  |             objects = BossManager() | ||||||
|  |  | ||||||
|  |             class Meta: | ||||||
|  |                 app_label = 'migrations' | ||||||
|  |                 apps = new_apps | ||||||
|  |  | ||||||
|  |         project_state = ProjectState.from_apps(new_apps) | ||||||
|  |         boss_state = project_state.models['migrations', 'boss'] | ||||||
|  |         self.assertEqual(boss_state.managers, [('objects', Boss.objects)]) | ||||||
|  |  | ||||||
|     def test_custom_default_manager(self): |     def test_custom_default_manager(self): | ||||||
|         new_apps = Apps(['migrations']) |         new_apps = Apps(['migrations']) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user