mirror of
https://github.com/django/django.git
synced 2025-05-05 06:27:31 +00:00
Fixed #35408 -- Optimized post-migrate permission creation.
co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
1a36dce9c5
commit
d2c5a30e5a
@ -46,6 +46,13 @@ def create_permissions(
|
|||||||
if not app_config.models_module:
|
if not app_config.models_module:
|
||||||
return
|
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
|
# Ensure that contenttypes are created for this app. Needed if
|
||||||
# 'django.contrib.auth' is in INSTALLED_APPS before
|
# 'django.contrib.auth' is in INSTALLED_APPS before
|
||||||
# 'django.contrib.contenttypes'.
|
# 'django.contrib.contenttypes'.
|
||||||
@ -62,28 +69,15 @@ def create_permissions(
|
|||||||
try:
|
try:
|
||||||
app_config = apps.get_app_config(app_label)
|
app_config = apps.get_app_config(app_label)
|
||||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||||
Permission = apps.get_model("auth", "Permission")
|
|
||||||
except LookupError:
|
except LookupError:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not router.allow_migrate_model(using, Permission):
|
models = list(app_config.get_models())
|
||||||
return
|
|
||||||
|
|
||||||
# This will hold the permissions we're looking for as
|
# Grab all the ContentTypes.
|
||||||
# (content_type, (codename, name))
|
ctypes = ContentType.objects.db_manager(using).get_for_models(
|
||||||
searched_perms = []
|
*models, for_concrete_models=False
|
||||||
# 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
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
# 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
|
# looking for. We don't need to check for codenames since we already have
|
||||||
@ -91,20 +85,22 @@ def create_permissions(
|
|||||||
all_perms = set(
|
all_perms = set(
|
||||||
Permission.objects.using(using)
|
Permission.objects.using(using)
|
||||||
.filter(
|
.filter(
|
||||||
content_type__in=ctypes,
|
content_type__in=set(ctypes.values()),
|
||||||
)
|
)
|
||||||
.values_list("content_type", "codename")
|
.values_list("content_type", "codename")
|
||||||
)
|
)
|
||||||
|
|
||||||
perms = []
|
perms = []
|
||||||
for ct, (codename, name) in searched_perms:
|
for model in models:
|
||||||
if (ct.pk, codename) not in all_perms:
|
ctype = ctypes[model]
|
||||||
permission = Permission()
|
for codename, name in _get_all_permissions(model._meta):
|
||||||
permission._state.db = using
|
if (ctype.pk, codename) not in all_perms:
|
||||||
permission.codename = codename
|
permission = Permission()
|
||||||
permission.name = name
|
permission._state.db = using
|
||||||
permission.content_type = ct
|
permission.codename = codename
|
||||||
perms.append(permission)
|
permission.name = name
|
||||||
|
permission.content_type = ctype
|
||||||
|
perms.append(permission)
|
||||||
|
|
||||||
Permission.objects.using(using).bulk_create(perms)
|
Permission.objects.using(using).bulk_create(perms)
|
||||||
if verbosity >= 2:
|
if verbosity >= 2:
|
||||||
|
@ -1528,7 +1528,7 @@ class CreatePermissionsMultipleDatabasesTests(TestCase):
|
|||||||
|
|
||||||
def test_set_permissions_fk_to_using_parameter(self):
|
def test_set_permissions_fk_to_using_parameter(self):
|
||||||
Permission.objects.using("other").delete()
|
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")
|
create_permissions(apps.get_app_config("auth"), verbosity=0, using="other")
|
||||||
self.assertIn("INSERT INTO", captured_queries[-1]["sql"].upper())
|
self.assertIn("INSERT INTO", captured_queries[-1]["sql"].upper())
|
||||||
self.assertGreater(Permission.objects.using("other").count(), 0)
|
self.assertGreater(Permission.objects.using("other").count(), 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user