Refs #29428 -- Fixed admin check crash when using a query expression in ModelAdmin.ordering.
This commit is contained in:
parent
0d8e3e608e
commit
ec2c9c3531
|
@ -10,6 +10,7 @@ from django.core import checks
|
||||||
from django.core.exceptions import FieldDoesNotExist
|
from django.core.exceptions import FieldDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.constants import LOOKUP_SEP
|
from django.db.models.constants import LOOKUP_SEP
|
||||||
|
from django.db.models.expressions import Combinable, F, OrderBy
|
||||||
from django.forms.models import (
|
from django.forms.models import (
|
||||||
BaseModelForm, BaseModelFormSet, _get_foreign_key,
|
BaseModelForm, BaseModelFormSet, _get_foreign_key,
|
||||||
)
|
)
|
||||||
|
@ -489,7 +490,13 @@ class BaseModelAdminChecks:
|
||||||
|
|
||||||
def _check_ordering_item(self, obj, model, field_name, label):
|
def _check_ordering_item(self, obj, model, field_name, label):
|
||||||
""" Check that `ordering` refers to existing fields. """
|
""" Check that `ordering` refers to existing fields. """
|
||||||
|
if isinstance(field_name, (Combinable, OrderBy)):
|
||||||
|
if not isinstance(field_name, OrderBy):
|
||||||
|
field_name = field_name.asc()
|
||||||
|
if isinstance(field_name.expression, F):
|
||||||
|
field_name = field_name.expression.name
|
||||||
|
else:
|
||||||
|
return []
|
||||||
if field_name == '?' and len(obj.ordering) != 1:
|
if field_name == '?' and len(obj.ordering) != 1:
|
||||||
return [
|
return [
|
||||||
checks.Error(
|
checks.Error(
|
||||||
|
|
|
@ -11,3 +11,6 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed admin changelist crash when using a query expression without ``asc()``
|
* Fixed admin changelist crash when using a query expression without ``asc()``
|
||||||
or ``desc()`` in the page's ordering (:ticket:`29428`).
|
or ``desc()`` in the page's ordering (:ticket:`29428`).
|
||||||
|
|
||||||
|
* Fixed admin check crash when using a query expression in
|
||||||
|
``ModelAdmin.ordering`` (:ticket:`29428`).
|
||||||
|
|
|
@ -3,6 +3,8 @@ from django.contrib.admin import BooleanFieldListFilter, SimpleListFilter
|
||||||
from django.contrib.admin.options import VERTICAL, ModelAdmin, TabularInline
|
from django.contrib.admin.options import VERTICAL, ModelAdmin, TabularInline
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.core.checks import Error
|
from django.core.checks import Error
|
||||||
|
from django.db.models import F
|
||||||
|
from django.db.models.functions import Upper
|
||||||
from django.forms.models import BaseModelFormSet
|
from django.forms.models import BaseModelFormSet
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
|
|
||||||
|
@ -829,6 +831,23 @@ class OrderingCheckTests(CheckTestCase):
|
||||||
|
|
||||||
self.assertIsValid(TestModelAdmin, ValidationTestModel)
|
self.assertIsValid(TestModelAdmin, ValidationTestModel)
|
||||||
|
|
||||||
|
def test_invalid_expression(self):
|
||||||
|
class TestModelAdmin(ModelAdmin):
|
||||||
|
ordering = (F('nonexistent'), )
|
||||||
|
|
||||||
|
self.assertIsInvalid(
|
||||||
|
TestModelAdmin, ValidationTestModel,
|
||||||
|
"The value of 'ordering[0]' refers to 'nonexistent', which is not "
|
||||||
|
"an attribute of 'modeladmin.ValidationTestModel'.",
|
||||||
|
'admin.E033'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_valid_expression(self):
|
||||||
|
class TestModelAdmin(ModelAdmin):
|
||||||
|
ordering = (Upper('name'), Upper('band__name').desc())
|
||||||
|
|
||||||
|
self.assertIsValid(TestModelAdmin, ValidationTestModel)
|
||||||
|
|
||||||
|
|
||||||
class ListSelectRelatedCheckTests(CheckTestCase):
|
class ListSelectRelatedCheckTests(CheckTestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue