diff options
author | Simon Charette <charettes@users.noreply.github.com> | 2019-01-17 09:22:14 -0600 |
---|---|---|
committer | Carlton Gibson <carlton.gibson@noumenal.es> | 2019-01-17 16:22:14 +0100 |
commit | f84ad16ba4bcf5fce6fc76593e0606573dec4697 (patch) | |
tree | 06009b6f480a1c12451342f19b61ce668d235423 /tests/admin_changelist | |
parent | aa5fd84f53f09338d01a3cfd9fa6ab08e418fe00 (diff) | |
download | django-f84ad16ba4bcf5fce6fc76593e0606573dec4697.tar.gz |
Refs #17198 -- Detected existing total ordering in admin changelist.
Appending pk is not necessary when a subset of the ordering expressions is
contained in a non-nullable unique contraint.
Related field ordering through lookups and related ordering introspection is
omitted for simplicitly purpose.
Diffstat (limited to 'tests/admin_changelist')
-rw-r--r-- | tests/admin_changelist/tests.py | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index df2c1b09f7..dfd8e91451 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -8,7 +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 import connection, models from django.db.models import F from django.db.models.fields import Field, IntegerField from django.db.models.functions import Upper @@ -16,7 +16,9 @@ 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, register_lookup +from django.test.utils import ( + CaptureQueriesContext, isolate_apps, register_lookup, +) from django.urls import reverse from django.utils import formats @@ -937,6 +939,81 @@ class ChangeListTests(TestCase): OrderedObjectAdmin.ordering = ['id', 'bool'] check_results_order(ascending=True) + @isolate_apps('admin_changelist') + def test_total_ordering_optimization(self): + class Related(models.Model): + unique_field = models.BooleanField(unique=True) + + class Meta: + ordering = ('unique_field',) + + class Model(models.Model): + unique_field = models.BooleanField(unique=True) + unique_nullable_field = models.BooleanField(unique=True, null=True) + related = models.ForeignKey(Related, models.CASCADE) + other_related = models.ForeignKey(Related, models.CASCADE) + related_unique = models.OneToOneField(Related, models.CASCADE) + field = models.BooleanField() + other_field = models.BooleanField() + null_field = models.BooleanField(null=True) + + class Meta: + unique_together = { + ('field', 'other_field'), + ('field', 'null_field'), + ('related', 'other_related_id'), + } + + class ModelAdmin(admin.ModelAdmin): + def get_queryset(self, request): + return Model.objects.none() + + request = self._mocked_authenticated_request('/', self.superuser) + site = admin.AdminSite(name='admin') + model_admin = ModelAdmin(Model, site) + change_list = model_admin.get_changelist_instance(request) + tests = ( + ([], ['-pk']), + # Unique non-nullable field. + (['unique_field'], ['unique_field']), + (['-unique_field'], ['-unique_field']), + # Unique nullable field. + (['unique_nullable_field'], ['unique_nullable_field', '-pk']), + # Field. + (['field'], ['field', '-pk']), + # Related field introspection is not implemented. + (['related__unique_field'], ['related__unique_field', '-pk']), + # Related attname unique. + (['related_unique_id'], ['related_unique_id']), + # Related ordering introspection is not implemented. + (['related_unique'], ['related_unique', '-pk']), + # Composite unique. + (['field', '-other_field'], ['field', '-other_field']), + # Composite unique nullable. + (['-field', 'null_field'], ['-field', 'null_field', '-pk']), + # Composite unique nullable. + (['-field', 'null_field'], ['-field', 'null_field', '-pk']), + # Composite unique nullable. + (['-field', 'null_field'], ['-field', 'null_field', '-pk']), + # Composite unique and nullable. + (['-field', 'null_field', 'other_field'], ['-field', 'null_field', 'other_field']), + # Composite unique attnames. + (['related_id', '-other_related_id'], ['related_id', '-other_related_id']), + # Composite unique names. + (['related', '-other_related_id'], ['related', '-other_related_id', '-pk']), + ) + # F() objects composite unique. + total_ordering = [F('field'), F('other_field').desc(nulls_last=True)] + # F() objects composite unique nullable. + non_total_ordering = [F('field'), F('null_field').desc(nulls_last=True)] + tests += ( + (total_ordering, total_ordering), + (non_total_ordering, non_total_ordering + ['-pk']), + ) + for ordering, expected in tests: + with self.subTest(ordering=ordering): + self.assertEqual(change_list._get_deterministic_ordering(ordering), expected) + def test_dynamic_list_filter(self): """ Regression tests for ticket #17646: dynamic list_filter support. |