Code

Ticket #17646: ticket17646.diff

File ticket17646.diff, 6.1 KB (added by mateusgondim, 2 years ago)

I created the hook there in options.py and replaced it in another method that was using the property directly.i also added a doc about the new method in the index.txt of admin, and in the section of minor features in release notes.Finally, i added a test in regression tests about that.

Line 
1diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
2index 2071792..0fe6bc4 100644
3--- a/django/contrib/admin/options.py
4+++ b/django/contrib/admin/options.py
5@@ -662,6 +662,13 @@ class ModelAdmin(BaseModelAdmin):
6             # Use only the first item in list_display as link
7             return list(list_display)[:1]
8 
9+    def get_list_filter(self, request):
10+        """
11+        Returns a sequence containing the fields to be displayed as filters in
12+        the right sidebar of the changelist page.
13+        """
14+        return self.list_filter
15+
16     def construct_change_message(self, request, form, formsets):
17         """
18         Construct a change message from a changed object.
19@@ -1112,6 +1119,7 @@ class ModelAdmin(BaseModelAdmin):
20 
21         list_display = self.get_list_display(request)
22         list_display_links = self.get_list_display_links(request, list_display)
23+        list_filter = self.get_list_filter(request)
24 
25         # Check actions to see if any are available on this changelist
26         actions = self.get_actions(request)
27@@ -1122,7 +1130,7 @@ class ModelAdmin(BaseModelAdmin):
28         ChangeList = self.get_changelist(request)
29         try:
30             cl = ChangeList(request, self.model, list_display,
31-                list_display_links, self.list_filter, self.date_hierarchy,
32+                list_display_links, list_filter, self.date_hierarchy,
33                 self.search_fields, self.list_select_related,
34                 self.list_per_page, self.list_max_show_all, self.list_editable,
35                 self)
36diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
37index f3e39b9..03a07ed 100644
38--- a/docs/ref/contrib/admin/index.txt
39+++ b/docs/ref/contrib/admin/index.txt
40@@ -1070,6 +1070,14 @@ templates used by the :class:`ModelAdmin` views:
41     changelist that will be linked to the change view, as described in the
42     :attr:`ModelAdmin.list_display_links` section.
43 
44+.. method:: ModelAdmin.get_list_filter(self, request)
45+
46+    .. versionadded:: 1.5
47+
48+    The ``get_list_filter`` is given the ``HttpRequest`` and is expected to
49+    return a ``list`` or ``tuple`` of field names that will be used as filters
50+    in the right sidebar of the changelist page.
51+
52 .. method:: ModelAdmin.get_urls(self)
53 
54     The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
55diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
56index 51e64bd..ef93a78 100644
57--- a/docs/releases/1.5.txt
58+++ b/docs/releases/1.5.txt
59@@ -60,6 +60,10 @@ Django 1.5 also includes several smaller improvements worth noting:
60 * In the localflavor for Canada, "pq" was added to the acceptable codes for
61   Quebec. It's an old abbreviation.
62 
63+* The filters in the changelist page of the admin interface can now be customized
64+  dependind on the request's context, by overriding the ModelAdmin.get_list_filter(self, request)
65+  method.
66+
67 Backwards incompatible changes in 1.5
68 =====================================
69 
70diff --git a/tests/regressiontests/admin_changelist/admin.py b/tests/regressiontests/admin_changelist/admin.py
71index 9ecfbc6..5751d04 100644
72--- a/tests/regressiontests/admin_changelist/admin.py
73+++ b/tests/regressiontests/admin_changelist/admin.py
74@@ -32,6 +32,7 @@ class ParentAdmin(admin.ModelAdmin):
75 class ChildAdmin(admin.ModelAdmin):
76     list_display = ['name', 'parent']
77     list_per_page = 10
78+    list_filter = ['parent', 'age']
79 
80     def queryset(self, request):
81         return super(ChildAdmin, self).queryset(request).select_related("parent__name")
82@@ -90,3 +91,14 @@ class SwallowAdmin(admin.ModelAdmin):
83     list_display = ('origin', 'load', 'speed')
84 
85 site.register(Swallow, SwallowAdmin)
86+
87+class DynamicListFilterChildAdmin(admin.ModelAdmin):
88+    list_filter = ('parent', 'name', 'age')
89+
90+    def get_list_filter(self, request):
91+        my_list_filter = super(DynamicListFilterChildAdmin, self).get_list_filter(request)
92+        if request.user.username == 'noparents':
93+            my_list_filter = list(my_list_filter)
94+            my_list_filter.remove('parent')
95+        return my_list_filter
96+
97diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
98index 62166ce..99a01d2 100644
99--- a/tests/regressiontests/admin_changelist/tests.py
100+++ b/tests/regressiontests/admin_changelist/tests.py
101@@ -15,7 +15,7 @@ from .admin import (ChildAdmin, QuartetAdmin, BandAdmin, ChordsBandAdmin,
102     GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin,
103     DynamicListDisplayLinksChildAdmin, CustomPaginationAdmin,
104     FilteredChildAdmin, CustomPaginator, site as custom_site,
105-    SwallowAdmin)
106+    SwallowAdmin, DynamicListFilterChildAdmin)
107 from .models import (Event, Child, Parent, Genre, Band, Musician, Group,
108     Quartet, Membership, ChordsMusician, ChordsBand, Invitation, Swallow,
109     UnorderedObject, OrderedObject)
110@@ -536,3 +536,31 @@ class ChangeListTests(TestCase):
111         check_results_order()
112         OrderedObjectAdmin.ordering = ['id', 'bool']
113         check_results_order(ascending=True)
114+
115+    def test_dynamic_list_filter(self):
116+        """
117+        Regression tests for ticket #17646: dynamic list_filter support.
118+        """
119+        parent = Parent.objects.create(name='parent')
120+        for i in range(10):
121+            Child.objects.create(name='child %s' % i, parent=parent)
122+
123+        user_noparents = self._create_superuser('noparents')
124+        user_parents = self._create_superuser('parents')
125+
126+        # Test with user 'noparents'
127+        m =  DynamicListFilterChildAdmin(Child, admin.site)
128+        request = self._mocked_authenticated_request('/child/', user_noparents)
129+        response = m.changelist_view(request)
130+
131+        list_filter = m.get_list_filter(request)
132+        self.assertEqual(list_filter, ['name', 'age'])
133+
134+        # Test with user 'parents'
135+        m = DynamicListFilterChildAdmin(Child, admin.site)
136+        request = self._mocked_authenticated_request('/child/', user_parents)
137+        response = m.changelist_view(request)
138+
139+        list_filter = m.get_list_filter(request)
140+        self.assertEqual(list_filter, ('parent', 'name', 'age'))
141+