From 283526a5a6854d1ba43f2b277d43cdd2b7f19c54 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Mon, 15 Aug 2011 09:01:12 +0000 Subject: [PATCH] Fixed #15206 -- Added select_related call to the permissions field of the GroupAdmin to lower the number of queries. Thanks, Chris Adams. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16620 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/admin.py | 9 +++++ tests/regressiontests/admin_views/tests.py | 40 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/django/contrib/auth/admin.py b/django/contrib/auth/admin.py index 5a8bdc2246..24d45e33bc 100644 --- a/django/contrib/auth/admin.py +++ b/django/contrib/auth/admin.py @@ -21,6 +21,15 @@ class GroupAdmin(admin.ModelAdmin): ordering = ('name',) filter_horizontal = ('permissions',) + def formfield_for_manytomany(self, db_field, request=None, **kwargs): + if db_field.name == 'permissions': + qs = kwargs.get('queryset', db_field.rel.to.objects) + # Avoid a major performance hit resolving permission names which + # triggers a content_type load: + kwargs['queryset'] = qs.select_related('content_type') + return super(GroupAdmin, self).formfield_for_manytomany(db_field, request=request, **kwargs) + + class UserAdmin(admin.ModelAdmin): add_form_template = 'admin/auth/user/add_form.html' change_user_password_template = None diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 8daa4662a9..0d1628c366 100644 --- a/tests/regressiontests/admin_views/tests.py +++ b/tests/regressiontests/admin_views/tests.py @@ -12,7 +12,7 @@ from django.core.files import temp as tempfile from django.core.urlresolvers import reverse # Register auth models with the admin. from django.contrib.auth import REDIRECT_FIELD_NAME, admin -from django.contrib.auth.models import User, Permission, UNUSABLE_PASSWORD +from django.contrib.auth.models import Group, User, Permission, UNUSABLE_PASSWORD from django.contrib.contenttypes.models import ContentType from django.contrib.admin.models import LogEntry, DELETION from django.contrib.admin.sites import LOGIN_FORM_KEY @@ -2911,6 +2911,44 @@ class UserAdminTest(TestCase): self.assertEqual(User.objects.count(), user_count + 1) self.assertNotEqual(new_user.password, UNUSABLE_PASSWORD) + def test_user_permission_performance(self): + u = User.objects.all()[0] + + with self.assertNumQueries(7): + response = self.client.get('/test_admin/admin/auth/user/%s/' % u.pk) + self.assertEqual(response.status_code, 200) + + +class GroupAdminTest(TestCase): + """ + Tests group CRUD functionality. + """ + fixtures = ['admin-views-users.xml'] + + def setUp(self): + self.client.login(username='super', password='secret') + + def tearDown(self): + self.client.logout() + + def test_save_button(self): + group_count = Group.objects.count() + response = self.client.post('/test_admin/admin/auth/group/add/', { + 'name': 'newgroup', + }) + + new_group = Group.objects.order_by('-id')[0] + self.assertRedirects(response, '/test_admin/admin/auth/group/') + self.assertEqual(Group.objects.count(), group_count + 1) + + def test_group_permission_performance(self): + g = Group.objects.create(name="test_group") + + with self.assertNumQueries(6): # instead of 259! + response = self.client.get('/test_admin/admin/auth/group/%s/' % g.pk) + self.assertEqual(response.status_code, 200) + + try: import docutils except ImportError: