Code

Ticket #14206: 14206_r16204.diff

File 14206_r16204.diff, 4.7 KB (added by cyrus, 3 years ago)
Line 
1Index: django/contrib/admin/options.py
2===================================================================
3--- django/contrib/admin/options.py     (revision 16288)
4+++ django/contrib/admin/options.py     (working copy)
5@@ -608,6 +608,13 @@
6             description = capfirst(action.replace('_', ' '))
7         return func, action, description
8 
9+    def get_list_display(self, request):
10+        """
11+        Return a sequence containing the fields to be displayed on the
12+        changelist.
13+        """
14+        return self.list_display
15+
16     def construct_change_message(self, request, form, formsets):
17         """
18         Construct a change message from a changed object.
19@@ -1026,7 +1033,7 @@
20         actions = self.get_actions(request)
21 
22         # Remove action checkboxes if there aren't any actions available.
23-        list_display = list(self.list_display)
24+        list_display = list(self.get_list_display(request))
25         if not actions:
26             try:
27                 list_display.remove('action_checkbox')
28Index: tests/regressiontests/admin_changelist/tests.py
29===================================================================
30--- tests/regressiontests/admin_changelist/tests.py     (revision 16288)
31+++ tests/regressiontests/admin_changelist/tests.py     (working copy)
32@@ -1,6 +1,9 @@
33+from django.conf import settings
34 from django.contrib import admin
35 from django.contrib.admin.options import IncorrectLookupParameters
36 from django.contrib.admin.views.main import ChangeList
37+from django.contrib.auth.models import User
38+from django.http import QueryDict
39 from django.template import Context, Template
40 from django.test import TransactionTestCase
41 from regressiontests.admin_changelist.models import Child, Parent
42@@ -143,7 +146,40 @@
43         self.assertEqual(cl.paginator.count, 30)
44         self.assertEqual(cl.paginator.page_range, [1, 2, 3])
45 
46+    def test_list_display(self):
47+        """
48+        Regression tests for #14206: dynamic list_display support.
49+        """
50+        parent = Parent.objects.create(name='parent')
51+        for i in range(10):
52+            Child.objects.create(name='child %s' % i, parent=parent)
53 
54+        user_noparents = User.objects.create(
55+            username='noparents',
56+            is_superuser=True)
57+        user_parents = User.objects.create(
58+            username='parents',
59+            is_superuser=True)
60+
61+        # Test with user 'noparents'
62+        m = DynamicListDisplayChildAdmin(Child, admin.site)
63+        request = ViewMockRequest(user_noparents)
64+        response = m.changelist_view(request)
65+        self.assertNotContains(response, 'Parent object')
66+
67+        # Test with user 'parents'
68+        m = DynamicListDisplayChildAdmin(Child, admin.site)
69+        request = ViewMockRequest(user_parents)
70+        response = m.changelist_view(request)
71+        self.assertContains(response, 'Parent object')
72+
73+        # Test default implementation
74+        m = ChildAdmin(Child, admin.site)
75+        request = ViewMockRequest(user_noparents)
76+        response = m.changelist_view(request)
77+        self.assertContains(response, 'Parent object')
78+
79+
80 class ChildAdmin(admin.ModelAdmin):
81     list_display = ['name', 'parent']
82     list_per_page = 10
83@@ -157,5 +193,25 @@
84         return super(FilteredChildAdmin, self).queryset(request).filter(
85             name__contains='filtered')
86 
87+class DynamicListDisplayChildAdmin(admin.ModelAdmin):
88+    list_display = ['name', 'parent']
89+
90+    def get_list_display(self, request):
91+        list_display = self.list_display
92+        if request.user.username == 'noparents':
93+            list_display.remove('parent')
94+
95+        return list_display
96+
97 class MockRequest(object):
98     GET = {}
99+
100+
101+class ViewMockRequest(object):
102+    def __init__(self, user):
103+        self.user = user
104+        self.COOKIES = {settings.CSRF_COOKIE_NAME: ''}
105+        self.GET = QueryDict('')
106+        self.POST = QueryDict('')
107+        self.META = {}
108+        self.method = 'GET'
109Index: docs/ref/contrib/admin/index.txt
110===================================================================
111--- docs/ref/contrib/admin/index.txt    (revision 16288)
112+++ docs/ref/contrib/admin/index.txt    (working copy)
113@@ -807,6 +807,15 @@
114     a ``list`` or ``tuple`` of field names that will be displayed as read-only,
115     as described above in the :attr:`ModelAdmin.readonly_fields` section.
116 
117+.. method:: ModelAdmin.get_list_display(self, request)
118+
119+    .. versionadded:: 1.2.6
120+
121+    The ``get_list_display`` method is given the ``HttpRequest`` and is
122+    expected to return a ``list`` or ``tuple`` of field names that will be
123+    displayed on the changelist view as described above in the
124+    :attr:`ModelAdmin.list_display` section.
125+
126 .. method:: ModelAdmin.get_urls(self)
127 
128     .. versionadded:: 1.1