Loading django/contrib/admin/options.py +9 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading @@ -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) Loading docs/ref/contrib/admin/index.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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``, Loading Loading @@ -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 Loading docs/releases/1.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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 ===================================== Loading tests/regressiontests/admin_changelist/admin.py +12 −0 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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 tests/regressiontests/admin_changelist/tests.py +24 −1 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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')) Loading
django/contrib/admin/options.py +9 −1 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) Loading @@ -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) Loading
docs/ref/contrib/admin/index.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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``, Loading Loading @@ -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 Loading
docs/releases/1.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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 ===================================== Loading
tests/regressiontests/admin_changelist/admin.py +12 −0 Original line number Diff line number Diff line Loading @@ -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") Loading Loading @@ -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
tests/regressiontests/admin_changelist/tests.py +24 −1 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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'))