Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #12875 -- Added get_ordering to ModelAdmin. Many thanks to Manu…

…el Saelices.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16383 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit f749bb829c715237c33c48c146ae78e1ed23ae71 1 parent f0adae4
@jezdez jezdez authored
View
9 django/contrib/admin/options.py
@@ -189,6 +189,12 @@ def _declared_fieldsets(self):
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 @@ def queryset(self, request):
"""
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 @@ def lookup_allowed(self, lookup, value):
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
9 django/contrib/admin/views/main.py
@@ -76,7 +76,7 @@ def __init__(self, request, model, list_display, list_display_links,
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 @@ def _get_default_ordering(self):
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
23 docs/ref/contrib/admin/index.txt
@@ -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
10 docs/releases/1.4.txt
@@ -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
8 tests/regressiontests/admin_ordering/models.py
@@ -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
22 tests/regressiontests/admin_ordering/tests.py
@@ -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 BandAdmin(ModelAdmin):
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
Please sign in to comment.
Something went wrong with that request. Please try again.