Fixed #28958 -- Fixed admin changelist crash when using a query expression in the page's ordering.

Thanks Tim Graham for the review.
This commit is contained in:
Mariusz Felisiak 2017-12-27 18:38:30 +01:00 committed by GitHub
parent 038ea4f859
commit c815213740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 1 deletions

View File

@ -15,6 +15,7 @@ from django.core.exceptions import (
) )
from django.core.paginator import InvalidPage from django.core.paginator import InvalidPage
from django.db import models from django.db import models
from django.db.models.expressions import F, OrderBy
from django.urls import reverse from django.urls import reverse
from django.utils.http import urlencode from django.utils.http import urlencode
from django.utils.translation import gettext from django.utils.translation import gettext
@ -287,7 +288,13 @@ class ChangeList:
# the right column numbers absolutely, because there might be more # the right column numbers absolutely, because there might be more
# than one column associated with that ordering, so we guess. # than one column associated with that ordering, so we guess.
for field in ordering: for field in ordering:
if field.startswith('-'): if isinstance(field, OrderBy):
if isinstance(field.expression, F):
order_type = 'desc' if field.descending else 'asc'
field = field.expression.name
else:
continue
elif field.startswith('-'):
field = field[1:] field = field[1:]
order_type = 'desc' order_type = 'desc'
else: else:

View File

@ -40,3 +40,6 @@ Bugfixes
* Fixed a crash when chaining ``values()`` or ``values_list()`` after * Fixed a crash when chaining ``values()`` or ``values_list()`` after
``QuerySet.select_for_update(of=(...))`` (:ticket:`28944`). ``QuerySet.select_for_update(of=(...))`` (:ticket:`28944`).
* Fixed admin changelist crash when using a query expression in the page's
ordering (:ticket:`28958`).

View File

@ -8,7 +8,9 @@ from django.contrib.admin.tests import AdminSeleniumTestCase
from django.contrib.admin.views.main import ALL_VAR, SEARCH_VAR from django.contrib.admin.views.main import ALL_VAR, SEARCH_VAR
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models import F
from django.db.models.fields import Field, IntegerField from django.db.models.fields import Field, IntegerField
from django.db.models.functions import Upper
from django.db.models.lookups import Contains, Exact from django.db.models.lookups import Contains, Exact
from django.template import Context, Template from django.template import Context, Template
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
@ -57,6 +59,20 @@ class ChangeListTests(TestCase):
request.user = user request.user = user
return request return request
def test_specified_ordering_by_f_expression(self):
class OrderedByFBandAdmin(admin.ModelAdmin):
list_display = ['name', 'genres', 'nr_of_members']
ordering = (
F('nr_of_members').desc(nulls_last=True),
Upper(F('name')).asc(),
F('genres').asc(),
)
m = OrderedByFBandAdmin(Band, custom_site)
request = self.factory.get('/band/')
cl = m.get_changelist_instance(request)
self.assertEqual(cl.get_ordering_field_columns(), {3: 'desc', 2: 'asc'})
def test_select_related_preserved(self): def test_select_related_preserved(self):
""" """
Regression test for #10348: ChangeList.get_queryset() shouldn't Regression test for #10348: ChangeList.get_queryset() shouldn't