mirror of
				https://github.com/django/django.git
				synced 2025-10-30 17:16:10 +00:00 
			
		
		
		
	[1.10.x] Fixed #27073 -- Removed duplicated managers in Model._meta.managers.
				
					
				
			Backport of d4eefc7e2a from master
			
			
This commit is contained in:
		| @@ -368,11 +368,16 @@ class Options(object): | |||||||
|     @cached_property |     @cached_property | ||||||
|     def managers(self): |     def managers(self): | ||||||
|         managers = [] |         managers = [] | ||||||
|  |         seen_managers = set() | ||||||
|         bases = (b for b in self.model.mro() if hasattr(b, '_meta')) |         bases = (b for b in self.model.mro() if hasattr(b, '_meta')) | ||||||
|         for depth, base in enumerate(bases): |         for depth, base in enumerate(bases): | ||||||
|             for manager in base._meta.local_managers: |             for manager in base._meta.local_managers: | ||||||
|  |                 if manager.name in seen_managers: | ||||||
|  |                     continue | ||||||
|  |  | ||||||
|                 manager = copy.copy(manager) |                 manager = copy.copy(manager) | ||||||
|                 manager.model = self.model |                 manager.model = self.model | ||||||
|  |                 seen_managers.add(manager.name) | ||||||
|                 managers.append((depth, manager.creation_counter, manager)) |                 managers.append((depth, manager.creation_counter, manager)) | ||||||
|  |  | ||||||
|                 # Used for deprecation of legacy manager inheritance, |                 # Used for deprecation of legacy manager inheritance, | ||||||
| @@ -386,7 +391,7 @@ class Options(object): | |||||||
|  |  | ||||||
|     @cached_property |     @cached_property | ||||||
|     def managers_map(self): |     def managers_map(self): | ||||||
|         return {manager.name: manager for manager in reversed(self.managers)} |         return {manager.name: manager for manager in self.managers} | ||||||
|  |  | ||||||
|     @cached_property |     @cached_property | ||||||
|     def base_manager(self): |     def base_manager(self): | ||||||
|   | |||||||
| @@ -56,3 +56,5 @@ Bugfixes | |||||||
| * Reallowed the ``{% for %}`` tag to unpack any iterable (:ticket:`27058`). | * Reallowed the ``{% for %}`` tag to unpack any iterable (:ticket:`27058`). | ||||||
|  |  | ||||||
| * Fixed ``makemigrations`` crash if a database is read-only (:ticket:`27054`). | * Fixed ``makemigrations`` crash if a database is read-only (:ticket:`27054`). | ||||||
|  |  | ||||||
|  | * Removed duplicated managers in ``Model._meta.managers`` (:ticket:`27073`). | ||||||
|   | |||||||
| @@ -286,6 +286,22 @@ class TestManagerInheritance(TestCase): | |||||||
|  |  | ||||||
|         self.assertIsInstance(MTIModel._base_manager, CustomManager) |         self.assertIsInstance(MTIModel._base_manager, CustomManager) | ||||||
|  |  | ||||||
|  |     def test_manager_no_duplicates(self): | ||||||
|  |         class CustomManager(models.Manager): | ||||||
|  |             pass | ||||||
|  |  | ||||||
|  |         class AbstractModel(models.Model): | ||||||
|  |             custom_manager = models.Manager() | ||||||
|  |  | ||||||
|  |             class Meta: | ||||||
|  |                 abstract = True | ||||||
|  |  | ||||||
|  |         class TestModel(AbstractModel): | ||||||
|  |             custom_manager = CustomManager() | ||||||
|  |  | ||||||
|  |         self.assertEqual(TestModel._meta.managers, (TestModel.custom_manager,)) | ||||||
|  |         self.assertEqual(TestModel._meta.managers_map, {'custom_manager': TestModel.custom_manager}) | ||||||
|  |  | ||||||
|  |  | ||||||
| @isolate_apps('managers_regress') | @isolate_apps('managers_regress') | ||||||
| class TestManagerDeprecations(TestCase): | class TestManagerDeprecations(TestCase): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user