Code

Ticket #6002: 00-admin-better-saving.5.diff

File 00-admin-better-saving.5.diff, 12.0 KB (added by shnur, 6 years ago)

Patch cleanly applies to revision 7875

Line 
1Index: django/contrib/admin/options.py
2===================================================================
3--- django/contrib/admin/options.py     (revision 7875)
4+++ django/contrib/admin/options.py     (working copy)
5@@ -353,113 +353,105 @@
6         for inline in self.inline_instances:
7             yield inline.get_formset(request, obj)
8 
9-    def save_add(self, request, model, form, formsets, post_url_continue):
10-        """
11-        Saves the object in the "add" stage and returns an HttpResponseRedirect.
12+    def save(self, request, form, formsets, original_obj, commit=True):
13+        """ Save new or changed object and its inlines. """
14+        new_obj = form.save(commit=commit)
15+        for formset in formsets:
16+            # HACK: it seems like the parent object should be passed into
17+            # a method of something, not just set as an attribute
18+            formset.instance = new_obj
19+            formset.save()
20+        return new_obj
21 
22-        `form` is a bound Form instance that's verified to be valid.
23-        """
24+    def log_add(self, request, form, formsets, new_obj):
25+        """ Log saving of new object and its inlines. """
26         from django.contrib.admin.models import LogEntry, ADDITION
27-        from django.contrib.contenttypes.models import ContentType
28-        opts = model._meta
29-        new_object = form.save(commit=True)
30+        user_id = request.user.id
31+        content_type_id = ContentType.objects.get_for_model(self.model).id
32+        object_id = new_obj._get_pk_val()
33+        LogEntry.objects.log_action(user_id, content_type_id, object_id, force_unicode(new_obj), ADDITION)
34 
35-        if formsets:
36-            for formset in formsets:
37-                # HACK: it seems like the parent obejct should be passed into
38-                # a method of something, not just set as an attribute
39-                formset.instance = new_object
40-                formset.save()
41-
42-        pk_value = new_object._get_pk_val()
43-        LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), ADDITION)
44-        msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
45-        # Here, we distinguish between different save types by checking for
46-        # the presence of keys in request.POST.
47-        if request.POST.has_key("_continue"):
48-            request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
49-            if request.POST.has_key("_popup"):
50-                post_url_continue += "?_popup=1"
51-            return HttpResponseRedirect(post_url_continue % pk_value)
52+    def log_change(self, request, form, formsets, original_obj, new_obj):
53+        """ Log saving of changed object and its inlines. """
54+        from django.contrib.admin.models import LogEntry, CHANGE
55+        user_id = request.user.id
56+        content_type_id = ContentType.objects.get_for_model(self.model).id
57+        object_id = new_obj._get_pk_val() 
58+        # Construct the change message. TODO: Temporarily commented-out,
59+        # as manipulator object doesn't exist anymore, and we don't yet
60+        # have a way to get fields_added, fields_changed, fields_deleted.
61+        #change_message = ' '.join(change_message)
62+        change_message = None
63+        if not change_message:
64+            change_message = _('No fields changed.')
65+        LogEntry.objects.log_action(user_id, content_type_id, object_id, force_unicode(new_obj), CHANGE, change_message)
66         
67-        if request.POST.has_key("_popup"):
68-            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
69+    def redirect_after_save(self, request, new_obj, add=False, change=False):
70+        """ Redirect after saving of new or changed object. """
71+        opts = self.opts
72+        pk_value = new_obj._get_pk_val()
73+
74+        # popup
75+        if request.POST.has_key('_popup'):
76+            if isinstance(pk_value, str): # Quote if string, so JavaScript doesn't think it's a variable.
77+                pk_value = '"%s"' % pk_value.replace('"', '\\"')
78+            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
79                 # escape() calls force_unicode.
80-                (escape(pk_value), escape(new_object)))
81-        elif request.POST.has_key("_addanother"):
82-            request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
83-            return HttpResponseRedirect(request.path)
84+                (escape(pk_value), escape(new_obj)))
85+
86+        # default message       
87+        if add:
88+            msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_obj}
89         else:
90-            request.user.message_set.create(message=msg)
91-            # Figure out where to redirect. If the user has change permission,
92-            # redirect to the change-list page for this object. Otherwise,
93-            # redirect to the admin index.
94-            if self.has_change_permission(request, None):
95-                post_url = '../'
96+            msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_obj}
97+
98+        # save as new
99+        if request.POST.has_key('_saveasnew'):
100+            if self.has_change_permission(request, new_obj):
101+                msg += ' ' + _('You may edit it again below.')
102+                redirect_url = '../%s/' % pk_value
103+            elif self.has_change_permission(request):
104+                redirect_url = '../'
105             else:
106-                post_url = '../../../'
107-            return HttpResponseRedirect(post_url)
108-    save_add = transaction.commit_on_success(save_add)
109+                redirect_url = '../../../'
110+        # save and add another
111+        elif request.POST.has_key('_addanother'):
112+            msg += ' ' + (_('You may add another %s below.') % opts.verbose_name)
113+            if add:
114+                redirect_url = request.path
115+            else:
116+                redirect_url = '../add/'
117+        # save and continue editing
118+        elif request.POST.has_key('_continue'):
119+            if self.has_change_permission(request, new_obj):
120+                msg += ' ' + _('You may edit it again below.')
121+                if add:
122+                    redirect_url = '../%s/' % pk_value
123+                else:
124+                    redirect_url = request.path
125+            elif self.has_change_permission(request):
126+                redirect_url = '../'
127+            else:
128+                redirect_url = '../../../'
129+        # save
130+        else:
131+            if self.has_change_permission(request):
132+                redirect_url = '../'
133+            else:
134+                redirect_url = '../../../'
135 
136-    def save_change(self, request, model, form, formsets=None):
137-        """
138-        Saves the object in the "change" stage and returns an HttpResponseRedirect.
139-
140-        `form` is a bound Form instance that's verified to be valid.
141+        # create message and redirect
142+        request.user.message_set.create(message=msg)
143+        return HttpResponseRedirect(redirect_url)
144         
145-        `formsets` is a sequence of InlineFormSet instances that are verified to be valid.
146-        """
147-        from django.contrib.admin.models import LogEntry, CHANGE
148-        from django.contrib.contenttypes.models import ContentType
149-        opts = model._meta
150-        new_object = form.save(commit=True)
151-        pk_value = new_object._get_pk_val()
152+    def save_add(self, request, form, formsets, commit=True):
153+        """ Save changed object and its inlines. """
154+        return self.save(request, form, formsets, None, commit)
155+    save_add = transaction.commit_on_success(save_add)
156 
157-        if formsets:
158-            for formset in formsets:
159-                formset.save()
160-
161-        # Construct the change message.                 
162-        change_message = []
163-        if form.changed_data:
164-            change_message.append(_('Changed %s.') % get_text_list(form.changed_data, _('and')))
165-           
166-        if formsets:
167-            for formset in formsets:
168-                for added_object in formset.new_objects:
169-                    change_message.append(_('Added %(name)s "%(object)s".')
170-                                          % {'name': added_object._meta.verbose_name,
171-                                             'object': added_object})
172-                for changed_object, changed_fields in formset.changed_objects:
173-                    change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')
174-                                          % {'list': get_text_list(changed_fields, _('and')),
175-                                             'name': changed_object._meta.verbose_name,
176-                                             'object': changed_object})
177-                for deleted_object in formset.deleted_objects:
178-                    change_message.append(_('Deleted %(name)s "%(object)s".')
179-                                          % {'name': deleted_object._meta.verbose_name,
180-                                             'object': deleted_object})
181-        change_message = ' '.join(change_message)
182-        if not change_message:
183-            change_message = _('No fields changed.')
184-        LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), CHANGE, change_message)
185-
186-        msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
187-        if request.POST.has_key("_continue"):
188-            request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
189-            if request.REQUEST.has_key('_popup'):
190-                return HttpResponseRedirect(request.path + "?_popup=1")
191-            else:
192-                return HttpResponseRedirect(request.path)
193-        elif request.POST.has_key("_saveasnew"):
194-            request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object})
195-            return HttpResponseRedirect("../%s/" % pk_value)
196-        elif request.POST.has_key("_addanother"):
197-            request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
198-            return HttpResponseRedirect("../add/")
199-        else:
200-            request.user.message_set.create(message=msg)
201-            return HttpResponseRedirect("../")
202+    def save_change(self, request, form, formsets, original_obj, commit=True):
203+        """ Save changed object and its inlines. """
204+        return self.save(request, form, formsets, original_obj, commit)
205     save_change = transaction.commit_on_success(save_change)
206 
207     def render_change_form(self, request, model, context, add=False, change=False, form_url='', obj=None):
208@@ -514,7 +506,9 @@
209                     instance=obj, save_as_new=request.POST.has_key("_saveasnew"))
210                 inline_formsets.append(inline_formset)
211             if all_valid(inline_formsets) and form.is_valid():
212-                return self.save_add(request, model, form, inline_formsets, '../%s/')
213+                new_obj = self.save_add(request, form, inline_formsets)
214+                self.log_add(request, form, inline_formsets, new_obj)
215+                return self.redirect_after_save(request, new_obj, add=True)
216         else:
217             form = ModelForm(initial=dict(request.GET.items()))
218             for FormSet in self.get_formsets(request):
219@@ -576,7 +570,9 @@
220                 inline_formsets.append(inline_formset)
221 
222             if all_valid(inline_formsets) and form.is_valid():
223-                return self.save_change(request, model, form, inline_formsets)
224+                new_obj = self.save_change(request, form, inline_formsets, obj)
225+                self.log_change(request, form, inline_formsets, obj, new_obj)
226+                return self.redirect_after_save(request, new_obj, change=True)
227         else:
228             form = ModelForm(instance=obj)
229             for FormSet in self.get_formsets(request, obj):