Code

Ticket #12962: modeladmin-12962.diff

File modeladmin-12962.diff, 3.5 KB (added by blinkylights, 4 years ago)

Ambiguous form actions

Line 
1Index: django/contrib/admin/options.py
2===================================================================
3--- django/contrib/admin/options.py     (revision 12814)
4+++ django/contrib/admin/options.py     (working copy)
5@@ -732,7 +732,7 @@
6 
7             # Get the list of selected PKs. If nothing's selected, we can't
8             # perform an action on it, so bail. Except we want to perform
9-            # the action explicitely on all objects.
10+            # the action explicitly on all objects.
11             selected = request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)
12             if not selected and not select_across:
13                 # Reminder that something needs to be selected or nothing will happen
14@@ -756,6 +756,7 @@
15         else:
16             msg = _("No action selected.")
17             self.message_user(request, msg)
18+            return None
19 
20     @csrf_protect_m
21     @transaction.commit_on_success
22@@ -974,20 +975,41 @@
23             return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')
24 
25         # If the request was POSTed, this might be a bulk action or a bulk edit.
26-        # Try to look up an action or confirmation first, but if this isn't an
27-        # action the POST will fall through to the bulk edit check, below.
28-        if actions and request.method == 'POST' and (helpers.ACTION_CHECKBOX_NAME in request.POST or 'index' in request.POST):
29-            response = self.response_action(request, queryset=cl.get_query_set())
30-            if response:
31-                return response
32+        # Try to look up an action or confirmation first, but if this isn't an action the POST
33+        # will fall through to the bulk edit check, below.
34 
35+        action_failed = False
36+
37+        # Actions with no confirmation
38+        if actions and request.method == 'POST' and 'index' in request.POST and '_save' not in request.POST:
39+            if len(request.POST.get(helpers.ACTION_CHECKBOX_NAME, [])):
40+                response = self.response_action(request, queryset=cl.get_query_set())
41+                if response:
42+                    return response
43+                else:
44+                    action_failed = True
45+            else:
46+                msg = _("Items must be selected in order to perform actions on them. No items have been changed.")
47+                self.message_user(request, msg)
48+                action_failed = True
49+
50+        # Actions with confirmation
51+        if actions and request.method == 'POST' and helpers.ACTION_CHECKBOX_NAME in request.POST and 'index' not in request.POST and '_save' not in request.POST:
52+            if len(request.POST.get(helpers.ACTION_CHECKBOX_NAME, [])):
53+                response = self.response_action(request, queryset=cl.get_query_set())
54+                if response:
55+                    return response
56+                else:
57+                    action_failed = True
58+
59+
60         # If we're allowing changelist editing, we need to construct a formset
61         # for the changelist given all the fields to be edited. Then we'll
62         # use the formset to validate/process POSTed data.
63         formset = cl.formset = None
64 
65         # Handle POSTed bulk-edit data.
66-        if request.method == "POST" and self.list_editable:
67+        if request.method == "POST" and self.list_editable and '_save' in request.POST and not action_failed:
68             FormSet = self.get_changelist_formset(request)
69             formset = cl.formset = FormSet(request.POST, request.FILES, queryset=cl.result_list)
70             if formset.is_valid():