mirror of
				https://github.com/django/django.git
				synced 2025-11-04 01:47:52 +03:00 
			
		
		
		
	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
	
	Block a user