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
|
return None
|
||||||
declared_fieldsets = property(_declared_fieldsets)
|
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):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
"""
|
"""
|
||||||
Hook for specifying custom readonly fields.
|
Hook for specifying custom readonly fields.
|
||||||
|
@ -208,7 +214,7 @@ class BaseModelAdmin(object):
|
||||||
"""
|
"""
|
||||||
qs = self.model._default_manager.get_query_set()
|
qs = self.model._default_manager.get_query_set()
|
||||||
# TODO: this should be handled by some parameter to the ChangeList.
|
# 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:
|
if ordering:
|
||||||
qs = qs.order_by(*ordering)
|
qs = qs.order_by(*ordering)
|
||||||
return qs
|
return qs
|
||||||
|
@ -260,6 +266,7 @@ class BaseModelAdmin(object):
|
||||||
clean_lookup = LOOKUP_SEP.join(parts)
|
clean_lookup = LOOKUP_SEP.join(parts)
|
||||||
return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
|
return clean_lookup in self.list_filter or clean_lookup == self.date_hierarchy
|
||||||
|
|
||||||
|
|
||||||
class ModelAdmin(BaseModelAdmin):
|
class ModelAdmin(BaseModelAdmin):
|
||||||
"Encapsulates all admin options and functionality for a given model."
|
"Encapsulates all admin options and functionality for a given model."
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ class ChangeList(object):
|
||||||
self.list_editable = ()
|
self.list_editable = ()
|
||||||
else:
|
else:
|
||||||
self.list_editable = list_editable
|
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 = request.GET.get(SEARCH_VAR, '')
|
||||||
self.query_set = self.get_query_set(request)
|
self.query_set = self.get_query_set(request)
|
||||||
self.get_results(request)
|
self.get_results(request)
|
||||||
|
@ -172,12 +172,13 @@ class ChangeList(object):
|
||||||
ordering = self.lookup_opts.ordering
|
ordering = self.lookup_opts.ordering
|
||||||
return ordering
|
return ordering
|
||||||
|
|
||||||
def get_ordering(self):
|
def get_ordering(self, request):
|
||||||
params = self.params
|
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
|
# options, then check the object's default ordering. Finally, a
|
||||||
# manually-specified ordering from the query string overrides anything.
|
# 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:
|
if ORDER_VAR in params:
|
||||||
# Clear ordering and used 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
|
If this isn't provided, the Django admin will use the model's default
|
||||||
ordering.
|
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
|
.. versionchanged:: 1.4
|
||||||
|
|
||||||
Django honors all elements in the list/tuple; before 1.4, only the first
|
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()
|
instance.save()
|
||||||
formset.save_m2m()
|
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)
|
.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
|
@ -1053,7 +1074,7 @@ templates used by the :class:`ModelAdmin` views:
|
||||||
.. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)
|
.. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs)
|
||||||
|
|
||||||
The ``formfield_for_foreignkey`` method on a ``ModelAdmin`` allows you to
|
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::
|
return a subset of objects for this foreign key field based on the user::
|
||||||
|
|
||||||
class MyModelAdmin(admin.ModelAdmin):
|
class MyModelAdmin(admin.ModelAdmin):
|
||||||
|
|
|
@ -73,10 +73,12 @@ documentation for :attr:`~django.contrib.admin.ModelAdmin.list_filter`.
|
||||||
Multiple sort in admin interface
|
Multiple sort in admin interface
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The admin change list now supports sorting on multiple columns. It respects all
|
The admin change list now supports sorting on multiple columns. It respects
|
||||||
elements of the :attr:`~django.contrib.admin.ModelAdmin.ordering` attribute, and
|
all elements of the :attr:`~django.contrib.admin.ModelAdmin.ordering`
|
||||||
sorting on multiple columns by clicking on headers is designed to work similarly
|
attribute, and sorting on multiple columns by clicking on headers is designed
|
||||||
to how desktop GUIs do it.
|
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
|
Tools for cryptographic signing
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -24,3 +24,11 @@ class SongInlineDefaultOrdering(admin.StackedInline):
|
||||||
class SongInlineNewOrdering(admin.StackedInline):
|
class SongInlineNewOrdering(admin.StackedInline):
|
||||||
model = Song
|
model = Song
|
||||||
ordering = ('duration', )
|
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 django.contrib.admin.options import ModelAdmin
|
||||||
|
|
||||||
from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering
|
from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering, DynOrderingBandAdmin
|
||||||
|
|
||||||
class TestAdminOrdering(TestCase):
|
class TestAdminOrdering(TestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -11,6 +12,7 @@ class TestAdminOrdering(TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
self.request_factory = RequestFactory()
|
||||||
b1 = Band(name='Aerosmith', bio='', rank=3)
|
b1 = Band(name='Aerosmith', bio='', rank=3)
|
||||||
b1.save()
|
b1.save()
|
||||||
b2 = Band(name='Radiohead', bio='', rank=1)
|
b2 = Band(name='Radiohead', bio='', rank=1)
|
||||||
|
@ -38,6 +40,22 @@ class TestAdminOrdering(TestCase):
|
||||||
names = [b.name for b in ma.queryset(None)]
|
names = [b.name for b in ma.queryset(None)]
|
||||||
self.assertEqual([u'Radiohead', u'Van Halen', u'Aerosmith'], names)
|
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):
|
class TestInlineModelAdminOrdering(TestCase):
|
||||||
"""
|
"""
|
||||||
Let's make sure that InlineModelAdmin.queryset uses the ordering we define
|
Let's make sure that InlineModelAdmin.queryset uses the ordering we define
|
||||||
|
|
Loading…
Reference in New Issue