Fixed #17646 -- Added a get_list_filter() method to ModelAdmin. Thanks to rasca for the suggestion and to mateusgondim for the patch.

This commit is contained in:
Julien Phalip 2012-11-25 20:39:23 +01:00
parent f26b956e80
commit ae206d78f6
5 changed files with 58 additions and 4 deletions

View File

@ -665,6 +665,13 @@ class ModelAdmin(BaseModelAdmin):
# Use only the first item in list_display as link # Use only the first item in list_display as link
return list(list_display)[:1] 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): def construct_change_message(self, request, form, formsets):
""" """
Construct a change message from a changed object. Construct a change message from a changed object.
@ -1192,6 +1199,7 @@ class ModelAdmin(BaseModelAdmin):
list_display = self.get_list_display(request) list_display = self.get_list_display(request)
list_display_links = self.get_list_display_links(request, list_display) 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 # Check actions to see if any are available on this changelist
actions = self.get_actions(request) actions = self.get_actions(request)
@ -1202,7 +1210,7 @@ class ModelAdmin(BaseModelAdmin):
ChangeList = self.get_changelist(request) ChangeList = self.get_changelist(request)
try: try:
cl = ChangeList(request, self.model, list_display, 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.search_fields, self.list_select_related,
self.list_per_page, self.list_max_show_all, self.list_editable, self.list_per_page, self.list_max_show_all, self.list_editable,
self) self)

View File

@ -570,8 +570,8 @@ subclass::
.. image:: _images/users_changelist.png .. image:: _images/users_changelist.png
``list_filter`` should be a list of elements, where each element should be ``list_filter`` should be a list or tuple of elements, where each element
of one of the following types: should be of one of the following types:
* a field name, where the specified field should be either a * a field name, where the specified field should be either a
``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``, ``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 changelist that will be linked to the change view, as described in the
:attr:`ModelAdmin.list_display_links` section. :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) .. method:: ModelAdmin.get_inline_instances(self, request, obj=None)
.. versionadded:: 1.5 .. versionadded:: 1.5

View File

@ -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 :func:`django.contrib.messages.add_message`. This is useful for generating
error messages from admin actions. 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 Backwards incompatible changes in 1.5
===================================== =====================================

View File

@ -32,6 +32,7 @@ class ParentAdmin(admin.ModelAdmin):
class ChildAdmin(admin.ModelAdmin): class ChildAdmin(admin.ModelAdmin):
list_display = ['name', 'parent'] list_display = ['name', 'parent']
list_per_page = 10 list_per_page = 10
list_filter = ['parent', 'age']
def queryset(self, request): def queryset(self, request):
return super(ChildAdmin, self).queryset(request).select_related("parent__name") return super(ChildAdmin, self).queryset(request).select_related("parent__name")
@ -90,3 +91,14 @@ class SwallowAdmin(admin.ModelAdmin):
list_display = ('origin', 'load', 'speed') list_display = ('origin', 'load', 'speed')
site.register(Swallow, SwallowAdmin) 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

View File

@ -17,7 +17,7 @@ from .admin import (ChildAdmin, QuartetAdmin, BandAdmin, ChordsBandAdmin,
GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin, GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin,
DynamicListDisplayLinksChildAdmin, CustomPaginationAdmin, DynamicListDisplayLinksChildAdmin, CustomPaginationAdmin,
FilteredChildAdmin, CustomPaginator, site as custom_site, FilteredChildAdmin, CustomPaginator, site as custom_site,
SwallowAdmin) SwallowAdmin, DynamicListFilterChildAdmin)
from .models import (Event, Child, Parent, Genre, Band, Musician, Group, from .models import (Event, Child, Parent, Genre, Band, Musician, Group,
Quartet, Membership, ChordsMusician, ChordsBand, Invitation, Swallow, Quartet, Membership, ChordsMusician, ChordsBand, Invitation, Swallow,
UnorderedObject, OrderedObject) UnorderedObject, OrderedObject)
@ -541,3 +541,26 @@ class ChangeListTests(TestCase):
check_results_order() check_results_order()
OrderedObjectAdmin.ordering = ['id', 'bool'] OrderedObjectAdmin.ordering = ['id', 'bool']
check_results_order(ascending=True) 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'))