Commit ae206d78 authored by Julien Phalip's avatar Julien Phalip
Browse files

Fixed #17646 -- Added a get_list_filter() method to ModelAdmin. Thanks to...

Fixed #17646 -- Added a get_list_filter() method to ModelAdmin. Thanks to rasca for the suggestion and to mateusgondim for the patch.
parent f26b956e
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -665,6 +665,13 @@ class ModelAdmin(BaseModelAdmin):
            # Use only the first item in list_display as link
            return list(list_display)[:1]

    def get_list_filter(self, request):
        """
        Returns a sequence containing the fields to be displayed as filters in
        the right sidebar of the changelist page.
        """
        return self.list_filter

    def construct_change_message(self, request, form, formsets):
        """
        Construct a change message from a changed object.
@@ -1192,6 +1199,7 @@ class ModelAdmin(BaseModelAdmin):

        list_display = self.get_list_display(request)
        list_display_links = self.get_list_display_links(request, list_display)
        list_filter = self.get_list_filter(request)

        # Check actions to see if any are available on this changelist
        actions = self.get_actions(request)
@@ -1202,7 +1210,7 @@ class ModelAdmin(BaseModelAdmin):
        ChangeList = self.get_changelist(request)
        try:
            cl = ChangeList(request, self.model, list_display,
                list_display_links, self.list_filter, self.date_hierarchy,
                list_display_links, list_filter, self.date_hierarchy,
                self.search_fields, self.list_select_related,
                self.list_per_page, self.list_max_show_all, self.list_editable,
                self)
+10 −2
Original line number Diff line number Diff line
@@ -570,8 +570,8 @@ subclass::

    .. image:: _images/users_changelist.png

    ``list_filter`` should be a list of elements, where each element should be
    of one of the following types:
    ``list_filter`` should be a list or tuple of elements, where each element
    should be of one of the following types:

    * a field name, where the specified field should be either a
      ``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``,
@@ -1076,6 +1076,14 @@ templates used by the :class:`ModelAdmin` views:
    changelist that will be linked to the change view, as described in the
    :attr:`ModelAdmin.list_display_links` section.

.. method:: ModelAdmin.get_list_filter(self, request)

    .. versionadded:: 1.5

    The ``get_list_filter`` method is given the ``HttpRequest`` and is expected
    to return the same kind of sequence type as for the
    :attr:`~ModelAdmin.list_filter` attribute.

.. method:: ModelAdmin.get_inline_instances(self, request, obj=None)

    .. versionadded:: 1.5
+3 −0
Original line number Diff line number Diff line
@@ -318,6 +318,9 @@ Django 1.5 also includes several smaller improvements worth noting:
  :func:`django.contrib.messages.add_message`. This is useful for generating
  error messages from admin actions.

* The admin's list filters can now be customized per-request thanks to the new
  :meth:`django.contrib.admin.ModelAdmin.get_list_filter` method.

Backwards incompatible changes in 1.5
=====================================

+12 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ class ParentAdmin(admin.ModelAdmin):
class ChildAdmin(admin.ModelAdmin):
    list_display = ['name', 'parent']
    list_per_page = 10
    list_filter = ['parent', 'age']

    def queryset(self, request):
        return super(ChildAdmin, self).queryset(request).select_related("parent__name")
@@ -90,3 +91,14 @@ class SwallowAdmin(admin.ModelAdmin):
    list_display = ('origin', 'load', 'speed')

site.register(Swallow, SwallowAdmin)

class DynamicListFilterChildAdmin(admin.ModelAdmin):
    list_filter = ('parent', 'name', 'age')

    def get_list_filter(self, request):
        my_list_filter = super(DynamicListFilterChildAdmin, self).get_list_filter(request)
        if request.user.username == 'noparents':
            my_list_filter = list(my_list_filter)
            my_list_filter.remove('parent')
        return my_list_filter
+24 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ from .admin import (ChildAdmin, QuartetAdmin, BandAdmin, ChordsBandAdmin,
    GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin,
    DynamicListDisplayLinksChildAdmin, CustomPaginationAdmin,
    FilteredChildAdmin, CustomPaginator, site as custom_site,
    SwallowAdmin)
    SwallowAdmin, DynamicListFilterChildAdmin)
from .models import (Event, Child, Parent, Genre, Band, Musician, Group,
    Quartet, Membership, ChordsMusician, ChordsBand, Invitation, Swallow,
    UnorderedObject, OrderedObject)
@@ -541,3 +541,26 @@ class ChangeListTests(TestCase):
        check_results_order()
        OrderedObjectAdmin.ordering = ['id', 'bool']
        check_results_order(ascending=True)

    def test_dynamic_list_filter(self):
        """
        Regression tests for ticket #17646: dynamic list_filter support.
        """
        parent = Parent.objects.create(name='parent')
        for i in range(10):
            Child.objects.create(name='child %s' % i, parent=parent)

        user_noparents = self._create_superuser('noparents')
        user_parents = self._create_superuser('parents')

        # Test with user 'noparents'
        m =  DynamicListFilterChildAdmin(Child, admin.site)
        request = self._mocked_authenticated_request('/child/', user_noparents)
        response = m.changelist_view(request)
        self.assertEqual(response.context_data['cl'].list_filter, ['name', 'age'])

        # Test with user 'parents'
        m = DynamicListFilterChildAdmin(Child, admin.site)
        request = self._mocked_authenticated_request('/child/', user_parents)
        response = m.changelist_view(request)
        self.assertEqual(response.context_data['cl'].list_filter, ('parent', 'name', 'age'))