Fixed #21924 -- Added the ability to specify a reverse order for admin_order_field.

Thanks Klemens Mantzos for the report and initial patch.
This commit is contained in:
Klemens Mantzos 2014-01-23 03:13:59 +01:00 committed by Tim Graham
parent 0242134d32
commit f683cb90be
6 changed files with 44 additions and 3 deletions

View File

@ -293,7 +293,11 @@ class ChangeList(six.with_metaclass(RenameChangeListMethods)):
order_field = self.get_ordering_field(field_name) order_field = self.get_ordering_field(field_name)
if not order_field: if not order_field:
continue # No 'admin_order_field', skip it continue # No 'admin_order_field', skip it
ordering.append(pfx + order_field) # reverse order if order_field has already "-" as prefix
if order_field.startswith('-') and pfx == "-":
ordering.append(order_field[1:])
else:
ordering.append(pfx + order_field)
except (IndexError, ValueError): except (IndexError, ValueError):
continue # Invalid ordering specified, skip it. continue # Invalid ordering specified, skip it.

View File

@ -664,6 +664,14 @@ subclass::
The above will tell Django to order by the ``first_name`` field when The above will tell Django to order by the ``first_name`` field when
trying to sort by ``colored_first_name`` in the admin. trying to sort by ``colored_first_name`` in the admin.
.. versionadded:: 1.7
To indicate descending order with ``admin_model_field`` you can use a
hyphen prefix on the field name. Using the above example, this would
look like::
colored_first_name.admin_order_field = '-first_name'
* Elements of ``list_display`` can also be properties. Please note however, * Elements of ``list_display`` can also be properties. Please note however,
that due to the way properties work in Python, setting that due to the way properties work in Python, setting
``short_description`` on a property is only possible when using the ``short_description`` on a property is only possible when using the

View File

@ -292,6 +292,10 @@ Minor features
<django.contrib.admin.ModelAdmin.view_on_site>` to control whether or not to <django.contrib.admin.ModelAdmin.view_on_site>` to control whether or not to
display the "View on site" link. display the "View on site" link.
* You can specify a descending ordering for a :attr:`ModelAdmin.list_display
<django.contrib.admin.ModelAdmin.list_display>` value by prefixing the
``admin_order_field`` value with a hyphen.
:mod:`django.contrib.auth` :mod:`django.contrib.auth`
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -76,7 +76,8 @@ class ChapterXtra1Admin(admin.ModelAdmin):
class ArticleAdmin(admin.ModelAdmin): class ArticleAdmin(admin.ModelAdmin):
list_display = ('content', 'date', callable_year, 'model_year', 'modeladmin_year') list_display = ('content', 'date', callable_year, 'model_year',
'modeladmin_year', 'model_year_reversed')
list_filter = ('date', 'section') list_filter = ('date', 'section')
view_on_site = False view_on_site = False
fieldsets = ( fieldsets = (

View File

@ -41,6 +41,11 @@ class Article(models.Model):
model_year.admin_order_field = 'date' model_year.admin_order_field = 'date'
model_year.short_description = '' model_year.short_description = ''
def model_year_reversed(self):
return self.date.year
model_year_reversed.admin_order_field = '-date'
model_year_reversed.short_description = ''
@python_2_unicode_compatible @python_2_unicode_compatible
class Book(models.Model): class Book(models.Model):

View File

@ -260,7 +260,7 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
def testChangeListSortingModelAdmin(self): def testChangeListSortingModelAdmin(self):
""" """
Ensure we can sort on a list_display field that is a ModelAdmin method Ensure we can sort on a list_display field that is a ModelAdmin method
(colunn 4 is 'modeladmin_year' in ArticleAdmin) (column 4 is 'modeladmin_year' in ArticleAdmin)
""" """
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'o': '4'}) response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'o': '4'})
self.assertContentBefore(response, 'Oldest content', 'Middle content', self.assertContentBefore(response, 'Oldest content', 'Middle content',
@ -268,6 +268,25 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
self.assertContentBefore(response, 'Middle content', 'Newest content', self.assertContentBefore(response, 'Middle content', 'Newest content',
"Results of sorting on ModelAdmin method are out of order.") "Results of sorting on ModelAdmin method are out of order.")
def testChangeListSortingModelAdminReverse(self):
"""
Ensure we can sort on a list_display field that is a ModelAdmin
method in reverse order (i.e. admin_order_field uses the '-' prefix)
(column 6 is 'model_year_reverse' in ArticleAdmin)
"""
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'o': '6'})
self.assertContentBefore(response, '2009', '2008',
"Results of sorting on ModelAdmin method are out of order.")
self.assertContentBefore(response, '2008', '2000',
"Results of sorting on ModelAdmin method are out of order.")
# Let's make sure the ordering is right and that we don't get a
# FieldError when we change to descending order
response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'o': '-6'})
self.assertContentBefore(response, '2000', '2008',
"Results of sorting on ModelAdmin method are out of order.")
self.assertContentBefore(response, '2008', '2009',
"Results of sorting on ModelAdmin method are out of order.")
def testChangeListSortingMultiple(self): def testChangeListSortingMultiple(self):
p1 = Person.objects.create(name="Chris", gender=1, alive=True) p1 = Person.objects.create(name="Chris", gender=1, alive=True)
p2 = Person.objects.create(name="Chris", gender=2, alive=True) p2 = Person.objects.create(name="Chris", gender=2, alive=True)