diff options
author | Adam Donaghy <adamdonaghy1994@gmail.com> | 2018-05-03 23:41:04 +1000 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2018-06-01 10:41:05 -0400 |
commit | b18650a2634890aa758abae2f33875daa13a9ba3 (patch) | |
tree | e614f32f63338aec5d913f33f76ef3786cac458c /tests/admin_changelist | |
parent | e1ebd22558342bb0088a3da3571863a20413fa2a (diff) | |
download | django-b18650a2634890aa758abae2f33875daa13a9ba3.tar.gz |
Fixed #28462 -- Decreased memory usage with ModelAdmin.list_editable.
Regression in 917cc288a38f3c114a5440f0749b7e5e1086eb36.
Diffstat (limited to 'tests/admin_changelist')
-rw-r--r-- | tests/admin_changelist/models.py | 3 | ||||
-rw-r--r-- | tests/admin_changelist/tests.py | 85 |
2 files changed, 85 insertions, 3 deletions
diff --git a/tests/admin_changelist/models.py b/tests/admin_changelist/models.py index 62268a2b79..81d7fdfb3a 100644 --- a/tests/admin_changelist/models.py +++ b/tests/admin_changelist/models.py @@ -1,3 +1,5 @@ +import uuid + from django.db import models @@ -73,6 +75,7 @@ class Invitation(models.Model): class Swallow(models.Model): + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4) origin = models.CharField(max_length=255) load = models.FloatField() speed = models.FloatField() diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index 20587613a7..9f9150f34d 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -8,6 +8,7 @@ from django.contrib.admin.tests import AdminSeleniumTestCase from django.contrib.admin.views.main import ALL_VAR, SEARCH_VAR from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType +from django.db import connection from django.db.models import F from django.db.models.fields import Field, IntegerField from django.db.models.functions import Upper @@ -15,6 +16,7 @@ from django.db.models.lookups import Contains, Exact from django.template import Context, Template, TemplateSyntaxError from django.test import TestCase, override_settings from django.test.client import RequestFactory +from django.test.utils import CaptureQueriesContext from django.urls import reverse from django.utils import formats @@ -732,9 +734,9 @@ class ChangeListTests(TestCase): 'form-INITIAL_FORMS': '3', 'form-MIN_NUM_FORMS': '0', 'form-MAX_NUM_FORMS': '1000', - 'form-0-id': str(d.pk), - 'form-1-id': str(c.pk), - 'form-2-id': str(a.pk), + 'form-0-uuid': str(d.pk), + 'form-1-uuid': str(c.pk), + 'form-2-uuid': str(a.pk), 'form-0-load': '9.0', 'form-0-speed': '9.0', 'form-1-load': '5.0', @@ -764,6 +766,83 @@ class ChangeListTests(TestCase): # No new swallows were created. self.assertEqual(len(Swallow.objects.all()), 4) + def test_get_edited_object_ids(self): + a = Swallow.objects.create(origin='Swallow A', load=4, speed=1) + b = Swallow.objects.create(origin='Swallow B', load=2, speed=2) + c = Swallow.objects.create(origin='Swallow C', load=5, speed=5) + superuser = self._create_superuser('superuser') + self.client.force_login(superuser) + changelist_url = reverse('admin:admin_changelist_swallow_changelist') + m = SwallowAdmin(Swallow, custom_site) + data = { + 'form-TOTAL_FORMS': '3', + 'form-INITIAL_FORMS': '3', + 'form-MIN_NUM_FORMS': '0', + 'form-MAX_NUM_FORMS': '1000', + 'form-0-uuid': str(a.pk), + 'form-1-uuid': str(b.pk), + 'form-2-uuid': str(c.pk), + 'form-0-load': '9.0', + 'form-0-speed': '9.0', + 'form-1-load': '5.0', + 'form-1-speed': '5.0', + 'form-2-load': '5.0', + 'form-2-speed': '4.0', + '_save': 'Save', + } + request = self.factory.post(changelist_url, data=data) + pks = m._get_edited_object_pks(request, prefix='form') + self.assertEqual(sorted(pks), sorted([str(a.pk), str(b.pk), str(c.pk)])) + + def test_get_list_editable_queryset(self): + a = Swallow.objects.create(origin='Swallow A', load=4, speed=1) + Swallow.objects.create(origin='Swallow B', load=2, speed=2) + data = { + 'form-TOTAL_FORMS': '2', + 'form-INITIAL_FORMS': '2', + 'form-MIN_NUM_FORMS': '0', + 'form-MAX_NUM_FORMS': '1000', + 'form-0-uuid': str(a.pk), + 'form-0-load': '10', + '_save': 'Save', + } + superuser = self._create_superuser('superuser') + self.client.force_login(superuser) + changelist_url = reverse('admin:admin_changelist_swallow_changelist') + m = SwallowAdmin(Swallow, custom_site) + request = self.factory.post(changelist_url, data=data) + queryset = m._get_list_editable_queryset(request, prefix='form') + self.assertEqual(queryset.count(), 1) + data['form-0-uuid'] = 'INVALD_PRIMARY_KEY' + # The unfiltered queryset is returned if there's invalid data. + request = self.factory.post(changelist_url, data=data) + queryset = m._get_list_editable_queryset(request, prefix='form') + self.assertEqual(queryset.count(), 2) + + def test_changelist_view_list_editable_changed_objects_uses_filter(self): + """list_editable edits use a filtered queryset to limit memory usage.""" + a = Swallow.objects.create(origin='Swallow A', load=4, speed=1) + Swallow.objects.create(origin='Swallow B', load=2, speed=2) + data = { + 'form-TOTAL_FORMS': '2', + 'form-INITIAL_FORMS': '2', + 'form-MIN_NUM_FORMS': '0', + 'form-MAX_NUM_FORMS': '1000', + 'form-0-uuid': str(a.pk), + 'form-0-load': '10', + '_save': 'Save', + } + superuser = self._create_superuser('superuser') + self.client.force_login(superuser) + changelist_url = reverse('admin:admin_changelist_swallow_changelist') + with CaptureQueriesContext(connection) as context: + response = self.client.post(changelist_url, data=data) + self.assertEqual(response.status_code, 200) + self.assertIn('WHERE', context.captured_queries[4]['sql']) + self.assertIn('IN', context.captured_queries[4]['sql']) + # Check only the first few characters since the UUID may have dashes. + self.assertIn(str(a.pk)[:8], context.captured_queries[4]['sql']) + def test_deterministic_order_for_unordered_model(self): """ The primary key is used in the ordering of the changelist's results to |