summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJani Tiainen <jani@tiainen.cc>2019-03-19 17:51:35 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-03-24 20:43:56 +0100
commit044cc544203fdcf2601ff200547ecae2e51a5db5 (patch)
tree7d49cb5ff82b7368e39456752ceab3ec8bc480bd
parentea60b7bc7464808e34e3cb0aac04455fdd8545eb (diff)
Fixed #30259 -- Added support for admin_order_field attribute on properties in ModelAdmin.list_display.
-rw-r--r--django/contrib/admin/templatetags/admin_list.py3
-rw-r--r--django/contrib/admin/views/main.py2
-rw-r--r--docs/ref/contrib/admin/index.txt6
-rw-r--r--docs/releases/3.0.txt3
-rw-r--r--tests/admin_views/admin.py2
-rw-r--r--tests/admin_views/models.py5
-rw-r--r--tests/admin_views/tests.py19
7 files changed, 36 insertions, 4 deletions
diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
index b03e4b6470..fe4249ae5b 100644
--- a/django/contrib/admin/templatetags/admin_list.py
+++ b/django/contrib/admin/templatetags/admin_list.py
@@ -128,6 +128,9 @@ def result_headers(cl):
continue
admin_order_field = getattr(attr, "admin_order_field", None)
+ # Set ordering for attr that is a property, if defined.
+ if isinstance(attr, property) and hasattr(attr, 'fget'):
+ admin_order_field = getattr(attr.fget, 'admin_order_field')
if not admin_order_field:
is_field_sortable = False
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 978910df26..7d8d33d9d7 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -264,6 +264,8 @@ class ChangeList:
attr = getattr(self.model_admin, field_name)
else:
attr = getattr(self.model, field_name)
+ if isinstance(attr, property) and hasattr(attr, 'fget'):
+ attr = attr.fget
return getattr(attr, 'admin_order_field', None)
def get_ordering(self, request, queryset):
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index b4fa8c5035..93679c46fd 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -754,8 +754,9 @@ subclass::
* Elements of ``list_display`` can also be properties. Please note however,
that due to the way properties work in Python, setting
- ``short_description`` on a property is only possible when using the
- ``property()`` function and **not** with the ``@property`` decorator.
+ ``short_description`` or ``admin_order_field`` on a property is only
+ possible when using the ``property()`` function and **not** with the
+ ``@property`` decorator.
For example::
@@ -766,6 +767,7 @@ subclass::
def my_property(self):
return self.first_name + ' ' + self.last_name
my_property.short_description = "Full name of the person"
+ my_property.admin_order_field = 'last_name'
full_name = property(my_property)
diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt
index 69925e7fca..47fa80d30b 100644
--- a/docs/releases/3.0.txt
+++ b/docs/releases/3.0.txt
@@ -44,7 +44,8 @@ Minor features
:mod:`django.contrib.admin`
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* ...
+* Added support for ``admin_order_field`` attribute on properties in
+ :attr:`.ModelAdmin.list_display`.
:mod:`django.contrib.admindocs`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 0b0ad41e2e..3e8df5b7c2 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -104,7 +104,7 @@ class ArticleAdmin(admin.ModelAdmin):
list_display = (
'content', 'date', callable_year, 'model_year', 'modeladmin_year',
'model_year_reversed', 'section', lambda obj: obj.title,
- 'order_by_expression',
+ 'order_by_expression', 'model_property_year',
)
list_editable = ('section',)
list_filter = ('date', 'section')
diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py
index d134b34923..aaf86ea1cd 100644
--- a/tests/admin_views/models.py
+++ b/tests/admin_views/models.py
@@ -55,6 +55,11 @@ class Article(models.Model):
model_year_reversed.admin_order_field = '-date'
model_year_reversed.short_description = ''
+ def property_year(self):
+ return self.date.year
+ property_year.admin_order_field = 'date'
+ model_property_year = property(property_year)
+
class Book(models.Model):
"""
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 3acbc3d7ed..87835eb37b 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -344,6 +344,25 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
"Results of sorting on callable are out of order."
)
+ def test_change_list_sorting_property(self):
+ """
+ Sort on a list_display field that is a property (column 10 is
+ a property in Article model).
+ """
+ response = self.client.get(reverse('admin:admin_views_article_changelist'), {'o': 10})
+ self.assertContentBefore(
+ response,
+ 'Oldest content',
+ 'Middle content',
+ 'Results of sorting on property are out of order.',
+ )
+ self.assertContentBefore(
+ response,
+ 'Middle content',
+ 'Newest content',
+ 'Results of sorting on property are out of order.',
+ )
+
def test_change_list_sorting_callable_query_expression(self):
"""
Query expressions may be used for admin_order_field. (column 9 is