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

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

Patch cleanly applies to revision 7875

  • django/contrib/admin/options.py

     
    353353        for inline in self.inline_instances:
    354354            yield inline.get_formset(request, obj)
    355355
    356     def save_add(self, request, model, form, formsets, post_url_continue):
    357         """
    358         Saves the object in the "add" stage and returns an HttpResponseRedirect.
     356    def save(self, request, form, formsets, original_obj, commit=True):
     357        """ Save new or changed object and its inlines. """
     358        new_obj = form.save(commit=commit)
     359        for formset in formsets:
     360            # HACK: it seems like the parent object should be passed into
     361            # a method of something, not just set as an attribute
     362            formset.instance = new_obj
     363            formset.save()
     364        return new_obj
    359365
    360         `form` is a bound Form instance that's verified to be valid.
    361         """
     366    def log_add(self, request, form, formsets, new_obj):
     367        """ Log saving of new object and its inlines. """
    362368        from django.contrib.admin.models import LogEntry, ADDITION
    363         from django.contrib.contenttypes.models import ContentType
    364         opts = model._meta
    365         new_object = form.save(commit=True)
     369        user_id = request.user.id
     370        content_type_id = ContentType.objects.get_for_model(self.model).id
     371        object_id = new_obj._get_pk_val()
     372        LogEntry.objects.log_action(user_id, content_type_id, object_id, force_unicode(new_obj), ADDITION)
    366373
    367         if formsets:
    368             for formset in formsets:
    369                 # HACK: it seems like the parent obejct should be passed into
    370                 # a method of something, not just set as an attribute
    371                 formset.instance = new_object
    372                 formset.save()
    373 
    374         pk_value = new_object._get_pk_val()
    375         LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), ADDITION)
    376         msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
    377         # Here, we distinguish between different save types by checking for
    378         # the presence of keys in request.POST.
    379         if request.POST.has_key("_continue"):
    380             request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
    381             if request.POST.has_key("_popup"):
    382                 post_url_continue += "?_popup=1"
    383             return HttpResponseRedirect(post_url_continue % pk_value)
     374    def log_change(self, request, form, formsets, original_obj, new_obj):
     375        """ Log saving of changed object and its inlines. """
     376        from django.contrib.admin.models import LogEntry, CHANGE
     377        user_id = request.user.id
     378        content_type_id = ContentType.objects.get_for_model(self.model).id
     379        object_id = new_obj._get_pk_val() 
     380        # Construct the change message. TODO: Temporarily commented-out,
     381        # as manipulator object doesn't exist anymore, and we don't yet
     382        # have a way to get fields_added, fields_changed, fields_deleted.
     383        #change_message = ' '.join(change_message)
     384        change_message = None
     385        if not change_message:
     386            change_message = _('No fields changed.')
     387        LogEntry.objects.log_action(user_id, content_type_id, object_id, force_unicode(new_obj), CHANGE, change_message)
    384388       
    385         if request.POST.has_key("_popup"):
    386             return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
     389    def redirect_after_save(self, request, new_obj, add=False, change=False):
     390        """ Redirect after saving of new or changed object. """
     391        opts = self.opts
     392        pk_value = new_obj._get_pk_val()
     393
     394        # popup
     395        if request.POST.has_key('_popup'):
     396            if isinstance(pk_value, str): # Quote if string, so JavaScript doesn't think it's a variable.
     397                pk_value = '"%s"' % pk_value.replace('"', '\\"')
     398            return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
    387399                # escape() calls force_unicode.
    388                 (escape(pk_value), escape(new_object)))
    389         elif request.POST.has_key("_addanother"):
    390             request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
    391             return HttpResponseRedirect(request.path)
     400                (escape(pk_value), escape(new_obj)))
     401
     402        # default message       
     403        if add:
     404            msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_obj}
    392405        else:
    393             request.user.message_set.create(message=msg)
    394             # Figure out where to redirect. If the user has change permission,
    395             # redirect to the change-list page for this object. Otherwise,
    396             # redirect to the admin index.
    397             if self.has_change_permission(request, None):
    398                 post_url = '../'
     406            msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_obj}
     407
     408        # save as new
     409        if request.POST.has_key('_saveasnew'):
     410            if self.has_change_permission(request, new_obj):
     411                msg += ' ' + _('You may edit it again below.')
     412                redirect_url = '../%s/' % pk_value
     413            elif self.has_change_permission(request):
     414                redirect_url = '../'
    399415            else:
    400                 post_url = '../../../'
    401             return HttpResponseRedirect(post_url)
    402     save_add = transaction.commit_on_success(save_add)
     416                redirect_url = '../../../'
     417        # save and add another
     418        elif request.POST.has_key('_addanother'):
     419            msg += ' ' + (_('You may add another %s below.') % opts.verbose_name)
     420            if add:
     421                redirect_url = request.path
     422            else:
     423                redirect_url = '../add/'
     424        # save and continue editing
     425        elif request.POST.has_key('_continue'):
     426            if self.has_change_permission(request, new_obj):
     427                msg += ' ' + _('You may edit it again below.')
     428                if add:
     429                    redirect_url = '../%s/' % pk_value
     430                else:
     431                    redirect_url = request.path
     432            elif self.has_change_permission(request):
     433                redirect_url = '../'
     434            else:
     435                redirect_url = '../../../'
     436        # save
     437        else:
     438            if self.has_change_permission(request):
     439                redirect_url = '../'
     440            else:
     441                redirect_url = '../../../'
    403442
    404     def save_change(self, request, model, form, formsets=None):
    405         """
    406         Saves the object in the "change" stage and returns an HttpResponseRedirect.
    407 
    408         `form` is a bound Form instance that's verified to be valid.
     443        # create message and redirect
     444        request.user.message_set.create(message=msg)
     445        return HttpResponseRedirect(redirect_url)
    409446       
    410         `formsets` is a sequence of InlineFormSet instances that are verified to be valid.
    411         """
    412         from django.contrib.admin.models import LogEntry, CHANGE
    413         from django.contrib.contenttypes.models import ContentType
    414         opts = model._meta
    415         new_object = form.save(commit=True)
    416         pk_value = new_object._get_pk_val()
     447    def save_add(self, request, form, formsets, commit=True):
     448        """ Save changed object and its inlines. """
     449        return self.save(request, form, formsets, None, commit)
     450    save_add = transaction.commit_on_success(save_add)
    417451
    418         if formsets:
    419             for formset in formsets:
    420                 formset.save()
    421 
    422         # Construct the change message.                 
    423         change_message = []
    424         if form.changed_data:
    425             change_message.append(_('Changed %s.') % get_text_list(form.changed_data, _('and')))
    426            
    427         if formsets:
    428             for formset in formsets:
    429                 for added_object in formset.new_objects:
    430                     change_message.append(_('Added %(name)s "%(object)s".')
    431                                           % {'name': added_object._meta.verbose_name,
    432                                              'object': added_object})
    433                 for changed_object, changed_fields in formset.changed_objects:
    434                     change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')
    435                                           % {'list': get_text_list(changed_fields, _('and')),
    436                                              'name': changed_object._meta.verbose_name,
    437                                              'object': changed_object})
    438                 for deleted_object in formset.deleted_objects:
    439                     change_message.append(_('Deleted %(name)s "%(object)s".')
    440                                           % {'name': deleted_object._meta.verbose_name,
    441                                              'object': deleted_object})
    442         change_message = ' '.join(change_message)
    443         if not change_message:
    444             change_message = _('No fields changed.')
    445         LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, force_unicode(new_object), CHANGE, change_message)
    446 
    447         msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
    448         if request.POST.has_key("_continue"):
    449             request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
    450             if request.REQUEST.has_key('_popup'):
    451                 return HttpResponseRedirect(request.path + "?_popup=1")
    452             else:
    453                 return HttpResponseRedirect(request.path)
    454         elif request.POST.has_key("_saveasnew"):
    455             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})
    456             return HttpResponseRedirect("../%s/" % pk_value)
    457         elif request.POST.has_key("_addanother"):
    458             request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
    459             return HttpResponseRedirect("../add/")
    460         else:
    461             request.user.message_set.create(message=msg)
    462             return HttpResponseRedirect("../")
     452    def save_change(self, request, form, formsets, original_obj, commit=True):
     453        """ Save changed object and its inlines. """
     454        return self.save(request, form, formsets, original_obj, commit)
    463455    save_change = transaction.commit_on_success(save_change)
    464456
    465457    def render_change_form(self, request, model, context, add=False, change=False, form_url='', obj=None):
     
    514506                    instance=obj, save_as_new=request.POST.has_key("_saveasnew"))
    515507                inline_formsets.append(inline_formset)
    516508            if all_valid(inline_formsets) and form.is_valid():
    517                 return self.save_add(request, model, form, inline_formsets, '../%s/')
     509                new_obj = self.save_add(request, form, inline_formsets)
     510                self.log_add(request, form, inline_formsets, new_obj)
     511                return self.redirect_after_save(request, new_obj, add=True)
    518512        else:
    519513            form = ModelForm(initial=dict(request.GET.items()))
    520514            for FormSet in self.get_formsets(request):
     
    576570                inline_formsets.append(inline_formset)
    577571
    578572            if all_valid(inline_formsets) and form.is_valid():
    579                 return self.save_change(request, model, form, inline_formsets)
     573                new_obj = self.save_change(request, form, inline_formsets, obj)
     574                self.log_change(request, form, inline_formsets, obj, new_obj)
     575                return self.redirect_after_save(request, new_obj, change=True)
    580576        else:
    581577            form = ModelForm(instance=obj)
    582578            for FormSet in self.get_formsets(request, obj):
Back to Top