summaryrefslogtreecommitdiff
path: root/tests/admin_changelist
diff options
context:
space:
mode:
authorFabio Sangiovanni <sjh+github@sanjioh.org>2020-01-20 20:50:30 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-02-19 09:36:23 +0100
commitb457068cf272bc9912187a2b7aaaa4445110735e (patch)
treed06738e90a1032b1d389af8176a96a97d64190b0 /tests/admin_changelist
parentd270c10a723ca04e467e08d6d8b38ae392191f2d (diff)
downloaddjango-b457068cf272bc9912187a2b7aaaa4445110735e.tar.gz
Fixed #31187 -- Fixed detecting of existing total ordering in admin changelist when using Meta.constraints.
Detection of existing total ordering in admin changelist now takes into account non-partial unique constraints.
Diffstat (limited to 'tests/admin_changelist')
-rw-r--r--tests/admin_changelist/tests.py92
1 files changed, 92 insertions, 0 deletions
diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py
index a4c220cb15..fa29886160 100644
--- a/tests/admin_changelist/tests.py
+++ b/tests/admin_changelist/tests.py
@@ -1058,6 +1058,98 @@ class ChangeListTests(TestCase):
with self.subTest(ordering=ordering):
self.assertEqual(change_list._get_deterministic_ordering(ordering), expected)
+ @isolate_apps('admin_changelist')
+ def test_total_ordering_optimization_meta_constraints(self):
+ class Related(models.Model):
+ unique_field = models.BooleanField(unique=True)
+
+ class Meta:
+ ordering = ('unique_field',)
+
+ class Model(models.Model):
+ field_1 = models.BooleanField()
+ field_2 = models.BooleanField()
+ field_3 = models.BooleanField()
+ field_4 = models.BooleanField()
+ field_5 = models.BooleanField()
+ field_6 = models.BooleanField()
+ nullable_1 = models.BooleanField(null=True)
+ nullable_2 = models.BooleanField(null=True)
+ related_1 = models.ForeignKey(Related, models.CASCADE)
+ related_2 = models.ForeignKey(Related, models.CASCADE)
+ related_3 = models.ForeignKey(Related, models.CASCADE)
+ related_4 = models.ForeignKey(Related, models.CASCADE)
+
+ class Meta:
+ constraints = [
+ *[
+ models.UniqueConstraint(fields=fields, name=''.join(fields))
+ for fields in (
+ ['field_1'],
+ ['nullable_1'],
+ ['related_1'],
+ ['related_2_id'],
+ ['field_2', 'field_3'],
+ ['field_2', 'nullable_2'],
+ ['field_2', 'related_3'],
+ ['field_3', 'related_4_id'],
+ )
+ ],
+ models.CheckConstraint(check=models.Q(id__gt=0), name='foo'),
+ models.UniqueConstraint(
+ fields=['field_5'],
+ condition=models.Q(id__gt=10),
+ name='total_ordering_1',
+ ),
+ models.UniqueConstraint(
+ fields=['field_6'],
+ condition=models.Q(),
+ name='total_ordering',
+ ),
+ ]
+
+ 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 = (
+ # Unique non-nullable field.
+ (['field_1'], ['field_1']),
+ # Unique nullable field.
+ (['nullable_1'], ['nullable_1', '-pk']),
+ # Related attname unique.
+ (['related_1_id'], ['related_1_id']),
+ (['related_2_id'], ['related_2_id']),
+ # Related ordering introspection is not implemented.
+ (['related_1'], ['related_1', '-pk']),
+ # Composite unique.
+ (['-field_2', 'field_3'], ['-field_2', 'field_3']),
+ # Composite unique nullable.
+ (['field_2', '-nullable_2'], ['field_2', '-nullable_2', '-pk']),
+ # Composite unique and nullable.
+ (
+ ['field_2', '-nullable_2', 'field_3'],
+ ['field_2', '-nullable_2', 'field_3'],
+ ),
+ # Composite field and related field name.
+ (['field_2', '-related_3'], ['field_2', '-related_3', '-pk']),
+ (['field_3', 'related_4'], ['field_3', 'related_4', '-pk']),
+ # Composite field and related field attname.
+ (['field_2', 'related_3_id'], ['field_2', 'related_3_id']),
+ (['field_3', '-related_4_id'], ['field_3', '-related_4_id']),
+ # Partial unique constraint is ignored.
+ (['field_5'], ['field_5', '-pk']),
+ # Unique constraint with an empty condition.
+ (['field_6'], ['field_6']),
+ )
+ 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.