mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #24701 -- Converted model manager names to unicode in migrations
Thanks to Reto Aebersold for reporting the issue and Tim Graham and Claude Paroz for the review.
This commit is contained in:
		| @@ -436,7 +436,7 @@ class ModelState(object): | ||||
|             bases = (models.Model,) | ||||
|  | ||||
|         # Constructs all managers on the model | ||||
|         managers = {} | ||||
|         managers_mapping = {} | ||||
|  | ||||
|         def reconstruct_manager(mgr): | ||||
|             as_manager, manager_path, qs_path, args, kwargs = mgr.deconstruct() | ||||
| @@ -448,16 +448,17 @@ class ModelState(object): | ||||
|                 instance = manager_class(*args, **kwargs) | ||||
|             # We rely on the ordering of the creation_counter of the original | ||||
|             # instance | ||||
|             managers[mgr.name] = (mgr.creation_counter, instance) | ||||
|             name = force_text(mgr.name) | ||||
|             managers_mapping[name] = (mgr.creation_counter, instance) | ||||
|  | ||||
|         if hasattr(model, "_default_manager"): | ||||
|             default_manager_name = model._default_manager.name | ||||
|             default_manager_name = force_text(model._default_manager.name) | ||||
|             # Make sure the default manager is always the first | ||||
|             if model._default_manager.use_in_migrations: | ||||
|                 reconstruct_manager(model._default_manager) | ||||
|             else: | ||||
|                 # Force this manager to be the first and thus default | ||||
|                 managers[default_manager_name] = (0, models.Manager()) | ||||
|                 managers_mapping[default_manager_name] = (0, models.Manager()) | ||||
|             # Sort all managers by their creation counter | ||||
|             for _, manager, _ in sorted(model._meta.managers): | ||||
|                 if manager.name == "_base_manager" or not manager.use_in_migrations: | ||||
| @@ -467,7 +468,7 @@ class ModelState(object): | ||||
|             # instance for further processing | ||||
|             managers = [ | ||||
|                 (name, instance) for name, (cc, instance) in | ||||
|                 sorted(managers.items(), key=lambda v: v[1]) | ||||
|                 sorted(managers_mapping.items(), key=lambda v: v[1]) | ||||
|             ] | ||||
|             if managers == [(default_manager_name, models.Manager())]: | ||||
|                 managers = [] | ||||
| @@ -513,6 +514,7 @@ class ModelState(object): | ||||
|         # Sort all managers by their creation counter | ||||
|         sorted_managers = sorted(self.managers, key=lambda v: v[1].creation_counter) | ||||
|         for mgr_name, manager in sorted_managers: | ||||
|             mgr_name = force_text(mgr_name) | ||||
|             as_manager, manager_path, qs_path, args, kwargs = manager.deconstruct() | ||||
|             if as_manager: | ||||
|                 qs_class = import_string(qs_path) | ||||
|   | ||||
| @@ -66,6 +66,9 @@ Bugfixes | ||||
| * Fixed a migration crash when adding new relations to models | ||||
|   (:ticket:`24573`). | ||||
|  | ||||
| * Fixed a migration crash when applying migrations with model managers on | ||||
|   Python 3 that were generated on Python 2 (:ticket:`24701`). | ||||
|  | ||||
| Optimizations | ||||
| ============= | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ from django.db.migrations.state import ( | ||||
|     InvalidBasesError, ModelState, ProjectState, get_related_models_recursive, | ||||
| ) | ||||
| from django.test import SimpleTestCase, TestCase, override_settings | ||||
| from django.utils import six | ||||
|  | ||||
| from .models import ( | ||||
|     FoodManager, FoodQuerySet, ModelWithCustomBase, NoMigrationFoodManager, | ||||
| @@ -144,6 +145,7 @@ class StateTests(TestCase): | ||||
|  | ||||
|         # The default manager is used in migrations | ||||
|         self.assertEqual([name for name, mgr in food_state.managers], ['food_mgr']) | ||||
|         self.assertTrue(all(isinstance(name, six.text_type) for name, mgr in food_state.managers)) | ||||
|         self.assertEqual(food_state.managers[0][1].args, ('a', 'b', 1, 2)) | ||||
|  | ||||
|         # No explicit managers defined. Migrations will fall back to the default | ||||
| @@ -153,11 +155,13 @@ class StateTests(TestCase): | ||||
|         # default | ||||
|         self.assertEqual([name for name, mgr in food_no_default_manager_state.managers], | ||||
|                          ['food_no_mgr', 'food_mgr']) | ||||
|         self.assertTrue(all(isinstance(name, six.text_type) for name, mgr in food_no_default_manager_state.managers)) | ||||
|         self.assertEqual(food_no_default_manager_state.managers[0][1].__class__, models.Manager) | ||||
|         self.assertIsInstance(food_no_default_manager_state.managers[1][1], FoodManager) | ||||
|  | ||||
|         self.assertEqual([name for name, mgr in food_order_manager_state.managers], | ||||
|                          ['food_mgr1', 'food_mgr2']) | ||||
|         self.assertTrue(all(isinstance(name, six.text_type) for name, mgr in food_order_manager_state.managers)) | ||||
|         self.assertEqual([mgr.args for name, mgr in food_order_manager_state.managers], | ||||
|                          [('a', 'b', 1, 2), ('x', 'y', 3, 4)]) | ||||
|  | ||||
| @@ -220,7 +224,7 @@ class StateTests(TestCase): | ||||
|                 # The ordering we really want is objects, mgr1, mgr2 | ||||
|                 ('default', base_mgr), | ||||
|                 ('food_mgr2', mgr2), | ||||
|                 ('food_mgr1', mgr1), | ||||
|                 (b'food_mgr1', mgr1), | ||||
|             ] | ||||
|         )) | ||||
|  | ||||
| @@ -234,6 +238,7 @@ class StateTests(TestCase): | ||||
|         managers = sorted(Food._meta.managers) | ||||
|         self.assertEqual([mgr.name for _, mgr, _ in managers], | ||||
|                          ['default', 'food_mgr1', 'food_mgr2']) | ||||
|         self.assertTrue(all(isinstance(mgr.name, six.text_type) for _, mgr, _ in managers)) | ||||
|         self.assertEqual([mgr.__class__ for _, mgr, _ in managers], | ||||
|                          [models.Manager, FoodManager, FoodManager]) | ||||
|         self.assertIs(managers[0][1], Food._default_manager) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user