[2.0.x] Fixed #28958 -- Fixed admin changelist crash when using a query expression in the page's ordering.
Thanks Tim Graham for the review.
Backport of c815213740
from master
This commit is contained in:
parent
1b27374b0d
commit
b54302d226
|
@ -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
|
||||||
|
@ -288,7 +289,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:
|
||||||
|
|
|
@ -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`).
|
||||||
|
|
|
@ -8,6 +8,8 @@ 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.functions import Upper
|
||||||
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
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
@ -55,6 +57,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
|
||||||
|
|
Loading…
Reference in New Issue