mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #35408 -- Optimized post-migrate permission creation.
co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							1a36dce9c5
						
					
				
				
					commit
					d2c5a30e5a
				
			| @@ -46,6 +46,13 @@ def create_permissions( | ||||
|     if not app_config.models_module: | ||||
|         return | ||||
|  | ||||
|     try: | ||||
|         Permission = apps.get_model("auth", "Permission") | ||||
|     except LookupError: | ||||
|         return | ||||
|     if not router.allow_migrate_model(using, Permission): | ||||
|         return | ||||
|  | ||||
|     # Ensure that contenttypes are created for this app. Needed if | ||||
|     # 'django.contrib.auth' is in INSTALLED_APPS before | ||||
|     # 'django.contrib.contenttypes'. | ||||
| @@ -62,48 +69,37 @@ def create_permissions( | ||||
|     try: | ||||
|         app_config = apps.get_app_config(app_label) | ||||
|         ContentType = apps.get_model("contenttypes", "ContentType") | ||||
|         Permission = apps.get_model("auth", "Permission") | ||||
|     except LookupError: | ||||
|         return | ||||
|  | ||||
|     if not router.allow_migrate_model(using, Permission): | ||||
|         return | ||||
|     models = list(app_config.get_models()) | ||||
|  | ||||
|     # This will hold the permissions we're looking for as | ||||
|     # (content_type, (codename, name)) | ||||
|     searched_perms = [] | ||||
|     # The codenames and ctypes that should exist. | ||||
|     ctypes = set() | ||||
|     for klass in app_config.get_models(): | ||||
|         # Force looking up the content types in the current database | ||||
|         # before creating foreign keys to them. | ||||
|         ctype = ContentType.objects.db_manager(using).get_for_model( | ||||
|             klass, for_concrete_model=False | ||||
|     # Grab all the ContentTypes. | ||||
|     ctypes = ContentType.objects.db_manager(using).get_for_models( | ||||
|         *models, for_concrete_models=False | ||||
|     ) | ||||
|  | ||||
|         ctypes.add(ctype) | ||||
|         for perm in _get_all_permissions(klass._meta): | ||||
|             searched_perms.append((ctype, perm)) | ||||
|  | ||||
|     # Find all the Permissions that have a content_type for a model we're | ||||
|     # looking for.  We don't need to check for codenames since we already have | ||||
|     # a list of the ones we're going to create. | ||||
|     all_perms = set( | ||||
|         Permission.objects.using(using) | ||||
|         .filter( | ||||
|             content_type__in=ctypes, | ||||
|             content_type__in=set(ctypes.values()), | ||||
|         ) | ||||
|         .values_list("content_type", "codename") | ||||
|     ) | ||||
|  | ||||
|     perms = [] | ||||
|     for ct, (codename, name) in searched_perms: | ||||
|         if (ct.pk, codename) not in all_perms: | ||||
|     for model in models: | ||||
|         ctype = ctypes[model] | ||||
|         for codename, name in _get_all_permissions(model._meta): | ||||
|             if (ctype.pk, codename) not in all_perms: | ||||
|                 permission = Permission() | ||||
|                 permission._state.db = using | ||||
|                 permission.codename = codename | ||||
|                 permission.name = name | ||||
|             permission.content_type = ct | ||||
|                 permission.content_type = ctype | ||||
|                 perms.append(permission) | ||||
|  | ||||
|     Permission.objects.using(using).bulk_create(perms) | ||||
|   | ||||
| @@ -1528,7 +1528,7 @@ class CreatePermissionsMultipleDatabasesTests(TestCase): | ||||
|  | ||||
|     def test_set_permissions_fk_to_using_parameter(self): | ||||
|         Permission.objects.using("other").delete() | ||||
|         with self.assertNumQueries(6, using="other") as captured_queries: | ||||
|         with self.assertNumQueries(4, using="other") as captured_queries: | ||||
|             create_permissions(apps.get_app_config("auth"), verbosity=0, using="other") | ||||
|         self.assertIn("INSERT INTO", captured_queries[-1]["sql"].upper()) | ||||
|         self.assertGreater(Permission.objects.using("other").count(), 0) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user