示例#1
0
 def _merge_item(self, original, draft_copy):
     """ Delete original, clean up and publish copy."""
     # Handle FK and M2M references.
     refs = filter(
         lambda obj: obj != draft_copy,
         get_referencing_objects(original)
     )
     for ref in refs:
         field_names = lookup_referencing_object_relationships(original, ref)
         for field_name in field_names:
             fld_class = ref._meta.get_field(field_name).__class__
             if issubclass(fld_class, models.fields.related.ManyToManyField):
                 getattr(ref, field_name).remove(original)
                 getattr(ref, field_name).add(draft_copy)
             else:
                 setattr(ref, field_name, draft_copy)
                 ref.save()
     # Handle generic references.
     for ref in get_generic_referencing_objects(original):
         generic_fk_field = [f for f in ref._meta.virtual_fields \
             if isinstance(f, generic.GenericForeignKey)
         ][0].name
         setattr(ref, generic_fk_field, draft_copy)
         ref.save()
     # Overwrite the old object.
     if self.slug:
         setattr(original, self.slug_field, original.slug + "-merge")
     original.save()
     if self.slug:
         import re
         slug = re.sub(
             "-draft-copy$", "", getattr(draft_copy, self.slug_field)
         )
         setattr(draft_copy, self.slug_field, slug)
     draft_copy.copy_of = None
     draft_copy.save()
     original.delete()
     draft_copy.publish()
     return draft_copy
示例#2
0
    def merge_view(self, request, object_id, extra_context=None):
        """
        The 'merge' admin view for this model. Allows a user to merge a copy 
        back over the original.
        """
        opts = self.model._meta
        app_label = opts.app_label

        if not self.draft_copy_allowed:
            return HttpResponseBadRequest("Draft copy not allowed for %s." % 
                force_unicode(opts.verbose_name_plural)
            )

        obj = self.get_object(request, unquote(object_id))

        # For our purposes, permission to merge is equivalent to 
        # has_change_permisison and has_delete_permission.
        if not self.has_change_permission(request, obj) \
            or not self.has_delete_permission(request, obj) :
            raise PermissionDenied
        if obj is None:
            raise Http404(_(
                '%(name)s object with primary key %(key)r does not exist.') %   
                {
                    'name': force_unicode(opts.verbose_name), 
                    'key': escape(object_id)
                }
            )
        if not obj.is_draft_copy():
            return HttpResponseBadRequest(_(
                'The %s object could not be merged because it is not a '
                'draft copy. There is nothing to merge it into.'
            ) % force_unicode(opts.verbose_name))

        # Populate deleted_objects, a data structure of all related objects
        # that will also be deleted when this copy is deleted.
        generic_refs = get_generic_referencing_objects(obj.copy_of)
        direct_refs = get_referencing_objects(obj.copy_of)
        direct_refs = filter(lambda o: obj != o, direct_refs)
        object_refs = [(unicode(o), o._meta.verbose_name) for o in \
            chain(direct_refs, generic_refs)
        ]
        perms_needed = False
        if request.POST: # The user has already confirmed the merge.
            if perms_needed:
                raise PermissionDenied            
            original = obj.copy_of
            original_pk = original.pk
            self._merge_item(original, obj)
            # Look up admin log entries for the old object and reassign them
            # to the new object.
            ctype = ContentType.objects.get_for_model(original)
            LogEntry.objects.filter(
                content_type=ctype,
                object_id=original_pk
            ).update(object_id=obj.pk)
            message = 'Merged %s "%s".' % (
                force_unicode(obj._meta.verbose_name),
                force_unicode(obj)
            )
            self.log_change(request, obj, message)
            self.message_user(
                request, 
                _('The %(name)s "%(obj)s" was merged successfully.') % {
                    'name': force_unicode(opts.verbose_name), 
                    'obj': force_unicode(obj)
                }
            )

            return HttpResponseRedirect("../../")

        context = {
            "title": _("Are you sure?"),
            "object_name": force_unicode(opts.verbose_name),
            "object": obj,
            "escaped_original": force_unicode(obj.copy_of), 
            "referencing_objects": object_refs,
            "opts": opts,
            "root_path": self.admin_site.root_path,
            "app_label": app_label,
        }
        context.update(extra_context or {})
        context_instance = template.RequestContext(
            request, 
            current_app=self.admin_site.name
        )
        return render_to_response(self.merge_form_template, context, 
            context_instance=context_instance
        )
示例#3
0
    def copy_view(self, request, object_id, extra_context=None):
        """
        Create a draft copy of the item after user has confirmed. 
        """
        opts = self.model._meta
        app_label = opts.app_label

        if not self.draft_copy_allowed:
            return HttpResponseBadRequest("Draft copy not allowed for %s." % 
                force_unicode(opts.verbose_name_plural)
            )

        obj = self.get_object(request, unquote(object_id))
        object_refs = None

        # For our purposes, permission to copy is equivalent to 
        # has_add_permisison.
        if not self.has_add_permission(request):
            raise PermissionDenied

        if obj is None:
            raise Http404(_(
                '%(name)s object with primary key %(key)r does not exist.') %   
                {
                    'name': force_unicode(opts.verbose_name), 
                    'key': escape(object_id)
                }
            )
    
        if request.POST: # The user has already confirmed the copy.
            if obj.is_draft_copy():
                self.message_user(
                    request, 
                    _('You cannot copy a draft copy.')
                )            
                return HttpResponseRedirect(request.path)
            if obj.get_draft_copy():
                self.message_user(
                    request, 
                    _('A draft copy already exists.')
                )
                return HttpResponseRedirect(request.path)
            copy = self._copy_item(obj)
            original_message = 'Created a draft copy for %s "%s".' % (
                force_unicode(obj._meta.verbose_name),
                force_unicode(obj)
            )
            copy_message = 'Copied from %s "%s".' % (
                force_unicode(obj._meta.verbose_name),
                force_unicode(obj)
            )
            self.log_change(request, obj, original_message)
            self.log_change(request, copy, copy_message)            
            self.message_user(
                request, 
                _('The %(name)s "%(obj)s" was copied successfully.') % {
                    'name': force_unicode(opts.verbose_name), 
                    'obj': force_unicode(obj)
                }
            )
            
            url = reverse(
                "admin:%s_%s_change" % (
                    app_label, 
                    self.model._meta.module_name
                ),
                args=(copy.id,)
            )
            return HttpResponseRedirect(url)

        if self.model.objects.filter(copy_of=obj).exists():
            draft_already_exists = True
            title = _("Draft Copy Exists")
            edit_copy_url = reverse(
                "admin:%s_%s_change" % (
                    app_label, 
                    self.model._meta.module_name
                ),
                args=(self.model.objects.filter(copy_of=obj)[0].id,)
            )
            
        else:
            draft_already_exists = False
            title = _("Are you sure?")
            edit_copy_url = None
            generic_refs = get_generic_referencing_objects(obj)
            direct_refs = get_referencing_objects(obj)
            object_refs = [(unicode(o), o._meta.verbose_name) for o in \
                chain(direct_refs, generic_refs)
            ]
            
        context = {
            "title": title,
            "object_name": force_unicode(opts.verbose_name),
            "object": obj,
            "referencing_objects": object_refs,
            "opts": opts,
            "root_path": self.admin_site.root_path,
            "app_label": app_label,
            'draft_already_exists': draft_already_exists,
            'edit_copy_url': edit_copy_url
        }
        context.update(extra_context or {})
        context_instance = template.RequestContext(
            request, 
            current_app=self.admin_site.name
        )
        return render_to_response(self.copy_form_template, context, 
            context_instance=context_instance
        )