Code

Ticket #10595: patch_django_10595.20090324-2.diff

File patch_django_10595.20090324-2.diff, 5.4 KB (added by david, 5 years ago)

Now with documentation and tests

Line 
1Index: django/contrib/admin/options.py
2===================================================================
3--- django/contrib/admin/options.py     (revision 10129)
4+++ django/contrib/admin/options.py     (working copy)
5@@ -207,7 +207,7 @@
6         for inline_class in self.inlines:
7             inline_instance = inline_class(self.model, self.admin_site)
8             self.inline_instances.append(inline_instance)
9-        if 'action_checkbox' not in self.list_display:
10+        if 'action_checkbox' not in self.list_display and self.actions is not None:
11             self.list_display = ['action_checkbox'] +  list(self.list_display)
12         if not self.list_display_links:
13             for name in self.list_display:
14@@ -421,7 +421,10 @@
15         """
16         actions = {}
17         for klass in [self.admin_site] + self.__class__.mro()[::-1]:
18-            for action in getattr(klass, 'actions', []):
19+            class_actions = getattr(klass, 'actions', [])
20+            if not class_actions:
21+                continue # avoid iteration over None value
22+            for action in class_actions:
23                 func, name, description = self.get_action(action)
24                 actions[name] = (func, name, description)
25         return actions
26@@ -948,8 +951,15 @@
27             media = self.media
28             
29         # Build the action form and populate it with available actions.
30-        action_form = self.action_form(auto_id=None)
31-        action_form.fields['action'].choices = self.get_action_choices(request)       
32+        if self.actions is None:
33+            action_form = False
34+            actions_on_top = False
35+            actions_on_bottom = False
36+        else:
37+            action_form = self.action_form(auto_id=None)
38+            action_form.fields['action'].choices = self.get_action_choices(request)
39+            actions_on_top = self.actions_on_top
40+            actions_on_bottom = self.actions_on_bottom
41 
42         context = {
43             'title': cl.title,
44@@ -960,8 +970,8 @@
45             'root_path': self.admin_site.root_path,
46             'app_label': app_label,
47             'action_form': action_form,
48-            'actions_on_top': self.actions_on_top,
49-            'actions_on_bottom': self.actions_on_bottom,
50+            'actions_on_top': actions_on_top,
51+            'actions_on_bottom': actions_on_bottom,
52         }
53         context.update(extra_context or {})
54         return render_to_response(self.change_list_template or [
55Index: django/contrib/admin/templates/admin/change_list.html
56===================================================================
57--- django/contrib/admin/templates/admin/change_list.html       (revision 10129)
58+++ django/contrib/admin/templates/admin/change_list.html       (working copy)
59@@ -9,6 +9,11 @@
60     <script type="text/javascript" src="../../jsi18n/"></script>
61   {% endif %}
62   {{ media }}
63+  {% if not actions_on_top and not actions_on_bottom %}
64+    <style>
65+      #changelist table thead th:first-child {width: inherit}
66+    </style>
67+  {% endif %}
68 {% endblock %}
69 
70 {% block bodyclass %}change-list{% endblock %}
71Index: tests/regressiontests/admin_views/tests.py
72===================================================================
73--- tests/regressiontests/admin_views/tests.py  (revision 10129)
74+++ tests/regressiontests/admin_views/tests.py  (working copy)
75@@ -939,3 +939,10 @@
76         }
77         response = self.client.post('/test_admin/admin/admin_views/externalsubscriber/', action_data)
78         self.failUnlessEqual(response.status_code, 302)
79+
80+    def test_model_without_action(self):
81+        "Tests a ModelAdmin without any action"
82+        response = self.client.get('/test_admin/admin/admin_views/oldsubscriber/')
83+        self.assertEquals(response.context["action_form"], False)
84+        self.assertEquals(response.context["actions_on_top"], False)
85+        self.assertEquals(response.context["actions_on_bottom"], False)
86Index: tests/regressiontests/admin_views/models.py
87===================================================================
88--- tests/regressiontests/admin_views/models.py (revision 10129)
89+++ tests/regressiontests/admin_views/models.py (working copy)
90@@ -221,6 +221,9 @@
91 class ExternalSubscriber(Subscriber):
92     pass
93 
94+class OldSubscriber(Subscriber):
95+    pass
96+
97 def external_mail(request, selected):
98     EmailMessage(
99         'Greetings from a function action',
100@@ -236,6 +239,9 @@
101 class ExternalSubscriberAdmin(admin.ModelAdmin):
102     actions = [external_mail, redirect_to]
103 
104+class OldSubscriberAdmin(admin.ModelAdmin):
105+    actions = None
106+
107 admin.site.register(Article, ArticleAdmin)
108 admin.site.register(CustomArticle, CustomArticleAdmin)
109 admin.site.register(Section, inlines=[ArticleInline])
110@@ -246,6 +252,7 @@
111 admin.site.register(Persona, PersonaAdmin)
112 admin.site.register(Subscriber, SubscriberAdmin)
113 admin.site.register(ExternalSubscriber, ExternalSubscriberAdmin)
114+admin.site.register(OldSubscriber, OldSubscriberAdmin)
115 
116 # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
117 # That way we cover all four cases:
118Index: docs/ref/contrib/admin/actions.txt
119===================================================================
120--- docs/ref/contrib/admin/actions.txt  (revision 10129)
121+++ docs/ref/contrib/admin/actions.txt  (working copy)
122@@ -237,3 +237,9 @@
123         
124     admin.site.add_action(export_selected_objects)
125     
126+Removing actions
127+----------------
128+
129+If you set ``None`` in ``actions``, this tells the :class:`ModelAdmin` to do
130+not display any dropdown menu nor checkboxes related to admin actions.
131+