From 34e545a93847142b112083b9858f76448f356711 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 1 Nov 2010 20:54:39 +0000 Subject: [PATCH] Restructure the create_permission signal handler to perform fewer SQL queries, this speeds up the test suite dramatically. git-svn-id: http://code.djangoproject.com/svn/django/trunk@14413 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/management/__init__.py | 49 ++++++++++++++++------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py index 49ab56a872..fe2db75b86 100644 --- a/django/contrib/auth/management/__init__.py +++ b/django/contrib/auth/management/__init__.py @@ -2,8 +2,9 @@ Creates permissions for all installed apps that need permissions. """ -from django.db.models import get_models, signals from django.contrib.auth import models as auth_app +from django.db.models import get_models, signals + def _get_permission_codename(action, opts): return u'%s_%s' % (action, opts.object_name.lower()) @@ -19,19 +20,43 @@ def create_permissions(app, created_models, verbosity, **kwargs): from django.contrib.contenttypes.models import ContentType app_models = get_models(app) + + # This will hold the permissions we're looking for as + # (content_type, (codename, name)) + searched_perms = set() + # The codenames and ctypes that should exist. + ctypes = set() + codenames = set() for klass in app_models: ctype = ContentType.objects.get_for_model(klass) - for codename, name in _get_all_permissions(klass._meta): - p, created = auth_app.Permission.objects.get_or_create( - codename=codename, - content_type__pk=ctype.id, - defaults={ - 'name': name, - 'content_type': ctype - } - ) - if created and verbosity >= 2: - print "Adding permission '%s'" % p + ctypes.add(ctype) + for perm in _get_all_permissions(klass._meta): + codenames.add(perm[0]) + searched_perms.add((ctype, perm)) + + # Find all the Permissions that a) have a content_type for a model we're + # looking for, and b) have a codename we're looking for. It doesn't need to + # have both, we have a list of exactly what we want, and it's faster to + # write the query with fewer conditions. + all_perms = set(auth_app.Permission.objects.filter( + content_type__in=ctypes, + codename__in=codenames + ).values_list( + "content_type", "codename" + )) + + for ctype, (codename, name) in searched_perms: + # If the permissions exists, move on. + if (ctype.pk, codename) in all_perms: + continue + p = auth_app.Permission.objects.create( + codename=codename, + name=name, + content_type=ctype + ) + if verbosity >= 2: + print "Adding permission '%s'" % p + def create_superuser(app, created_models, verbosity, **kwargs): from django.core.management import call_command