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:
parent
f0adae4c6e
commit
f749bb829c
|
@ -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."
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue