Fixed #12875 -- Added get_ordering to ModelAdmin. Many thanks to Manuel Saelices.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16383 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2011-06-12 13:04:53 +00:00
parent f0adae4c6e
commit f749bb829c
6 changed files with 69 additions and 12 deletions

View File

@ -189,6 +189,12 @@ class BaseModelAdmin(object):
return None
declared_fieldsets = property(_declared_fieldsets)
def get_ordering(self, request):
"""
Hook for specifying field ordering.
"""
return self.ordering or () # otherwise we might try to *None, which is bad ;)
def get_readonly_fields(self, request, obj=None):
"""
Hook for specifying custom readonly fields.
@ -208,7 +214,7 @@ class BaseModelAdmin(object):
"""
qs = self.model._default_manager.get_query_set()
# TODO: this should be handled by some parameter to the ChangeList.
ordering = self.ordering or () # otherwise we might try to *None, which is bad ;)
ordering = self.get_ordering(request)
if ordering:
qs = qs.order_by(*ordering)
return qs
@ -260,6 +266,7 @@ class BaseModelAdmin(object):
clean_lookup = LOOKUP_SEP.join(parts)
return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
class ModelAdmin(BaseModelAdmin):
"Encapsulates all admin options and functionality for a given model."

View File

@ -76,7 +76,7 @@ class ChangeList(object):
self.list_editable = ()
else:
self.list_editable = list_editable
self.ordering = self.get_ordering()
self.ordering = self.get_ordering(request)
self.query = request.GET.get(SEARCH_VAR, '')
self.query_set = self.get_query_set(request)
self.get_results(request)
@ -172,12 +172,13 @@ class ChangeList(object):
ordering = self.lookup_opts.ordering
return ordering
def get_ordering(self):
def get_ordering(self, request):
params = self.params
# For ordering, first check the "ordering" parameter in the admin
# For ordering, first check the if exists the "get_ordering" method
# in model admin, then check "ordering" parameter in the admin
# options, then check the object's default ordering. Finally, a
# manually-specified ordering from the query string overrides anything.
ordering = self._get_default_ordering()
ordering = self.model_admin.get_ordering(request) or self._get_default_ordering()
if ORDER_VAR in params:
# Clear ordering and used params

View File

@ -704,6 +704,11 @@ subclass::
If this isn't provided, the Django admin will use the model's default
ordering.
.. versionadded:: 1.4
If you need to specify a dynamic order (for example depending on user or
language) you can implement a :meth:`~ModelAdmin.get_ordering` method.
.. versionchanged:: 1.4
Django honors all elements in the list/tuple; before 1.4, only the first
@ -957,6 +962,22 @@ templates used by the :class:`ModelAdmin` views:
instance.save()
formset.save_m2m()
.. method:: ModelAdmin.get_ordering(self, request)
.. versionadded:: 1.4
The ``get_ordering`` method takes a``request`` as parameter and
is expected to return a ``list`` or ``tuple`` for ordering similiar
to the :attr:`ordering` attribute. For example::
class PersonAdmin(ModelAdmin):
def get_ordering(self, request):
if request.user.is_superuser:
return ['name', 'rank']
else:
return ['name']
.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
.. versionadded:: 1.2
@ -1053,7 +1074,7 @@ templates used by the :class:`ModelAdmin` views:
.. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)
The ``formfield_for_foreignkey`` method on a ``ModelAdmin`` allows you to
override the default formfield for a foreign key field. For example, to
override the default formfield for a foreign keys field. For example, to
return a subset of objects for this foreign key field based on the user::
class MyModelAdmin(admin.ModelAdmin):

View File

@ -73,10 +73,12 @@ documentation for :attr:`~django.contrib.admin.ModelAdmin.list_filter`.
Multiple sort in admin interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The admin change list now supports sorting on multiple columns. It respects all
elements of the :attr:`~django.contrib.admin.ModelAdmin.ordering` attribute, and
sorting on multiple columns by clicking on headers is designed to work similarly
to how desktop GUIs do it.
The admin change list now supports sorting on multiple columns. It respects
all elements of the :attr:`~django.contrib.admin.ModelAdmin.ordering`
attribute, and sorting on multiple columns by clicking on headers is designed
to work similarly to how desktop GUIs do it. The new hook
:meth:`~django.contrib.admin.ModelAdmin.get_ordering` for specifying the
ordering dynamically (e.g. depending on the request) has also been added.
Tools for cryptographic signing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -24,3 +24,11 @@ class SongInlineDefaultOrdering(admin.StackedInline):
class SongInlineNewOrdering(admin.StackedInline):
model = Song
ordering = ('duration', )
class DynOrderingBandAdmin(admin.ModelAdmin):
def get_ordering(self, request):
if request.user.is_superuser:
return ['rank']
else:
return ['name']

View File

@ -1,7 +1,8 @@
from django.test import TestCase
from django.test import TestCase, RequestFactory
from django.contrib.auth.models import User
from django.contrib.admin.options import ModelAdmin
from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering
from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering, DynOrderingBandAdmin
class TestAdminOrdering(TestCase):
"""
@ -11,6 +12,7 @@ class TestAdminOrdering(TestCase):
"""
def setUp(self):
self.request_factory = RequestFactory()
b1 = Band(name='Aerosmith', bio='', rank=3)
b1.save()
b2 = Band(name='Radiohead', bio='', rank=1)
@ -38,6 +40,22 @@ class TestAdminOrdering(TestCase):
names = [b.name for b in ma.queryset(None)]
self.assertEqual([u'Radiohead', u'Van Halen', u'Aerosmith'], names)
def test_dynamic_ordering(self):
"""
Let's use a custom ModelAdmin that changes the ordering dinamically.
"""
super_user = User.objects.create(username='admin', is_superuser=True)
other_user = User.objects.create(username='other')
request = self.request_factory.get('/')
request.user = super_user
ma = DynOrderingBandAdmin(Band, None)
names = [b.name for b in ma.queryset(request)]
self.assertEqual([u'Radiohead', u'Van Halen', u'Aerosmith'], names)
request.user = other_user
names = [b.name for b in ma.queryset(request)]
self.assertEqual([u'Aerosmith', u'Radiohead', u'Van Halen'], names)
class TestInlineModelAdminOrdering(TestCase):
"""
Let's make sure that InlineModelAdmin.queryset uses the ordering we define