Exemplo n.º 1
0
 def version_status_change_view(self, request, object_id, version_id, status, extra_context=None):
     revision = get_object_or_404(Version, pk=version_id).revision
     latest_approved_revision = Version.objects.latest_approved(self.content_type, object_id).revision
     if (revision.status == VERSION_STATUS_NEED_ATTENTION):
         revision.status = status
         revision.update_moderation(request.user)
         revision.save()
         if status == VERSION_STATUS_APPROVED:
             revision.revert(latest_approved_revision)
     return HttpResponseRedirect(version_history_url(object_id, self.admin_site.name, self.model._meta))
Exemplo n.º 2
0
    def delete_view(self, request, object_id, extra_context=None):
        "The 'delete' admin view for this model."
        opts = self.model._meta
        app_label = opts.app_label

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

        if 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)})

        using = router.db_for_write(self.model)

        # Populate deleted_objects, a data structure of all related objects that
        # will also be deleted.
        (deleted_objects, perms_needed, protected) = get_deleted_objects(
            [obj], opts, request.user, self.admin_site, using)

        if request.POST: # The user has already confirmed the deletion.
            if perms_needed:
                raise PermissionDenied
            raw_obj = obj.object_version.object
            obj_display = force_unicode(obj)
            self.log_deletion(request, obj, obj_display)
            self.delete_model(request, obj)

            self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.')
                % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj_display)})

            if not self.has_change_permission(request, None):
                return HttpResponseRedirect(reverse('admin:index',
                                                    current_app=self.admin_site.name))
            return HttpResponseRedirect(
                version_history_url(raw_obj.id, self.admin_site.name, raw_obj._meta))

        object_name = force_unicode(opts.verbose_name)

        if perms_needed or protected:
            title = _("Cannot delete %(name)s") % {"name": object_name}
        else:
            title = _("Are you sure?")

        context = {
            "title": title,
            "object_name": object_name,
            "object": obj,
            "deleted_objects": deleted_objects,
            "perms_lacking": perms_needed,
            "protected": protected,
            "opts": opts,
            "app_label": app_label,
        }
        context.update(extra_context or {})

        return TemplateResponse(request, self.delete_confirmation_template or [
            "admin/%s/%s/delete_confirmation.html" % (app_label, opts.object_name.lower()),
            "admin/%s/delete_confirmation.html" % app_label,
            "admin/delete_confirmation.html"
        ], context, current_app=self.admin_site.name)
Exemplo n.º 3
0
    def process_common_post(self, request, obj, moderator, revision, form, formsets):
        latest_approved_revision = Version.objects.latest_approved(self.content_type, obj.pk).revision
        comment = request.POST.get("moderator_new_comment", "")

        changes = False
        if formsets:
            for formset in formsets:
                changes = (hasattr(formset, 'new_objects')
                    or hasattr(formset, 'changed_objects')
                    or hasattr(formset, 'deleted_objects'))
                if changes:
                    break
        changes = changes or form.has_changed()

        status_changed = False
        if request.POST.has_key("_reject"):
            status_changed = True
            revision.status = VERSION_STATUS_REJECTED
            if comment:
                revision.comment = comment
        if request.POST.has_key("_approve"):
            status_changed = True
            if changes:
                if revision.status == VERSION_STATUS_NEED_ATTENTION:
                    # TODO: can be branged?
                    revision.status = VERSION_STATUS_DRAFT
                    revision.update_moderation(moderator)
                    revision.save()
                self.save_with_relations(request, obj, form, formsets)
                revision = self.revision_manager.save_revision(
                    self.get_revision_data(request, obj, VERSION_TYPE_CHANGE),
                    parent = revision,
                    user = moderator,
                    comment = comment,
                    status = VERSION_STATUS_APPROVED,
                    ignore_duplicates = self.ignore_duplicate_revisions,
                    db = self.revision_context_manager.get_db(),)
            else:
                revision.status = VERSION_STATUS_APPROVED
                revision.revert(latest_approved_revision)
        if status_changed:
            revision.update_moderation(moderator)
            revision.save()
            return HttpResponseRedirect(
                version_history_url(obj.id, self.admin_site.name, self.model._meta))

        if request.POST.has_key('_recover'):
            self.save_with_relations(request, obj, form, formsets)
            revision = self.revision_manager.save_revision(
                self.get_revision_data(request, obj, VERSION_TYPE_RECOVER),
                parent = revision,
                user = moderator,
                comment = _(u"Deleted object was recovered."),
                status = VERSION_STATUS_APPROVED,
                ignore_duplicates = self.ignore_duplicate_revisions,
                db = self.revision_context_manager.get_db(),
            )
            return HttpResponseRedirect(
                version_edit_url(
                    obj.id, revision.version(obj.id, self.content_type).pk, self.admin_site.name, self.model._meta))

        if request.POST.has_key('_toapprove'):
            if changes or revision.status == VERSION_STATUS_REJECTED:
                self.save_with_relations(request, obj, form, formsets)
                revision_parent = revision
                revision = self.revision_manager.save_revision(
                    self.get_revision_data(request, obj, VERSION_TYPE_CHANGE),
                    user = request.user,
                    comment = comment,
                    parent = revision_parent,
                    ignore_duplicates = self.ignore_duplicate_revisions,
                    db = self.revision_context_manager.get_db(),
                )
                if (revision_parent.status == VERSION_STATUS_NEED_ATTENTION):
                    revision_parent.status = VERSION_STATUS_DRAFT
                    revision_parent.save()
                latest_approved_revision.revert(revision)
            if revision.status != VERSION_STATUS_APPROVED:
                revision.status = VERSION_STATUS_NEED_ATTENTION
                revision.save()
            return HttpResponseRedirect(
                version_edit_url(obj.id, revision.version(obj.id, self.content_type).pk, self.admin_site.name, self.model._meta))

        if request.POST.has_key('_tohistory'):
            if changes:
                self.save_with_relations(request, obj, form, formsets)
                revision = self.revision_manager.save_revision(
                    self.get_revision_data(request, obj, VERSION_TYPE_CHANGE),
                    user = request.user,
                    comment = comment,
                    parent = revision,
                    ignore_duplicates = self.ignore_duplicate_revisions,
                    db = self.revision_context_manager.get_db(),
                )
                latest_approved_revision.revert(revision)
                return HttpResponseRedirect(
                    version_edit_url(
                        obj.id, revision.version(obj.id, self.content_type).pk, self.admin_site.name, self.model._meta))
            else:
                return HttpResponseRedirect(".")

        if any(i in request.POST.keys() for i in ["_addanother", "_continue", "_save"]):
            auto_approve = is_user_content_admin(moderator)

            # TODO: improve changes detection for inlines and save only if changes were done
            self.save_with_relations(request, obj, form, formsets)
            if changes:
                # self.save_with_relations(request, obj, form, formsets)
                revision = self.revision_manager.save_revision(
                    self.get_revision_data(request, obj, VERSION_TYPE_CHANGE),
                    user = request.user,
                    comment = comment,
                    parent = revision,
                    status = VERSION_STATUS_APPROVED if auto_approve else VERSION_STATUS_DRAFT,
                    ignore_duplicates = self.ignore_duplicate_revisions,
                    db = self.revision_context_manager.get_db(),
                )
                if not auto_approve:
                    latest_approved_revision.revert(revision)
                return HttpResponseRedirect(reverse('admin:%s_%s_change' %
                    (obj._meta.app_label, obj._meta.module_name),
                    args=(obj.id,),
                    current_app=self.admin_site.name))
            elif auto_approve:
            # TODO: improve changes detection for inlines and use this instead of current elif statement:
            # elif auto_approve and (revision.children.exists() or revision.status == VERSION_STATUS_REJECTED):
                revision = self.revision_manager.save_revision(
                    self.get_revision_data(request, obj, VERSION_TYPE_CHANGE),
                    user = request.user,
                    comment = comment,
                    parent = revision,
                    status = VERSION_STATUS_APPROVED,
                    ignore_duplicates = self.ignore_duplicate_revisions,
                    db = self.revision_context_manager.get_db(),
                )
                return HttpResponseRedirect(reverse('admin:%s_%s_change' % (
                    obj._meta.app_label, obj._meta.module_name),
                    args=(obj.id,),
                    current_app=self.admin_site.name))

        return HttpResponseRedirect(".")
Exemplo n.º 4
0
    def render_version_form(self, request, version, form_template, extra_context, editing=False, recovering=False):
        obj = version.object_version.object
        object_id = obj.pk

        if (version.revision.deleted and version.revision.children.exists()):
            return HttpResponseNotFound(
                _(u"<p>Deleted object \"%s\" is already recovered. You cannot recover it again.</p>") % version)

        latest_approved = Version.objects.latest_approved(self.content_type, object_id)
        if (latest_approved.revision.deleted and not recovering):
            return HttpResponseNotFound(_(u"<p>You cannot view versions of deleted object.</p>"))

        model = self.model
        opts = model._meta
        v_opts = Version._meta

        ModelForm = self.get_form(request, obj)
        formsets = []

        is_approved = version.revision.status == VERSION_STATUS_APPROVED
        is_rejected = version.revision.status == VERSION_STATUS_REJECTED
        is_pending = version.revision.status == VERSION_STATUS_NEED_ATTENTION

        if request.method == 'POST':
            obj_copy = copy.deepcopy(obj)

            # This section is copied directly from the model admin change view
            # method.  Maybe one day there will be a hook for doing this better.
            form = ModelForm(request.POST, request.FILES, instance=obj_copy, initial=self.get_revision_form_data(request, obj_copy, version))
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=True)
                # HACK: If the value of a file field is None, remove the file from the model.
                for field in new_object._meta.fields:
                    if isinstance(field, models.FileField) and field.name in form.cleaned_data and form.cleaned_data[field.name] is None:
                        setattr(new_object, field.name, None)
            else:
                form_validated = False
                new_object = obj
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request, new_object),
                                       self.get_inline_instances(request)):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(request.POST, request.FILES,
                                  instance=new_object, prefix=prefix,
                                  queryset=inline.queryset(request))
                self._hack_inline_formset_initial(FormSet, formset, obj, version)
                # Add this hacked formset to the form.
                formsets.append(formset)
            if all_valid(formsets) and form_validated:
                return self.process_common_post(
                    request, new_object, request.user, version.revision, form, formsets)
        else:
            # This is a mutated version of the code in the standard model admin
            # change_view.  Once again, a hook for this kind of functionality
            # would be nice.  Unfortunately, it results in doubling the number
            # of queries required to construct the formets.
            form = ModelForm(instance=obj, initial=self.get_revision_form_data(request, obj, version))
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request, obj), self.get_inline_instances(request)):
                # This code is standard for creating the formset.
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=obj, prefix=prefix,
                                  queryset=inline.queryset(request))
                self._hack_inline_formset_initial(FormSet, formset, obj, version)
                # Add this hacked formset to the form.
                formsets.append(formset)
        # Generate admin form helper.
        adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj),
            self.prepopulated_fields, self.get_readonly_fields(request, obj),
            model_admin=self)
        media = self.media + adminForm.media
        # Generate formset helpers.
        inline_admin_formsets = []
        for inline, formset in zip(self.get_inline_instances(request), formsets):
            fieldsets = list(inline.get_fieldsets(request, obj))
            readonly = list(inline.get_readonly_fields(request, obj))
            prepopulated = inline.get_prepopulated_fields(request, obj)
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
                fieldsets, prepopulated, readonly, model_admin=self)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media

        if not recovering:
            if is_approved:
                messages.success(request, _("Current object was approved by admin."))
            elif is_rejected:
                messages.error(request, _("Current object was rejected by admin."))
            elif is_pending:
                messages.warning(request, _("Current object is waiting for admin approvement."))
            if version.revision.get_siblings().exclude(deleted=True).count() and (version.revision.parent is not None):
                messages.warning(request, _("Current object has an alternative version."))

        # Generate the context.
        context = {
            'title': _("Edit %(name)s") % {'name': obj},
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'is_popup': False,
            'media': mark_safe(media),
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': opts.app_label,
            'add': False,
            'change': True,
            'has_add_permission': self.has_add_permission(request),
            'has_change_permission': self.has_change_permission(request, obj),
            'has_delete_permission': self.has_delete_permission(request, obj),
            'has_file_field': True,
            'has_absolute_url': False,
            'ordered_objects': opts.get_ordered_objects(),
            'form_url': mark_safe(request.path),
            'opts': opts,
            'content_type_id': self.content_type.id,
            'save_as': False,
            'save_on_top': self.save_on_top,
            'changelist_url': reverse("%s:%s_%s_changelist" % (
                self.admin_site.name, opts.app_label, opts.module_name)),
            'change_url': reverse("%s:%s_%s_change" % (
                self.admin_site.name, opts.app_label, opts.module_name), args=(quote(obj.pk),)),
            'changes_url': version_view_changes_url(obj.pk, version.pk, self.admin_site.name, opts),

            'edit_url': version_edit_url(obj.pk, version.pk, self.admin_site.name, opts),
            'parent_url': version_edit_url(
                obj.pk, version.revision.parent.version(obj.pk, self.content_type).pk, self.admin_site.name, opts
            ) if version.revision.parent else None,
            'history_url': version_history_url(obj.pk, self.admin_site.name, opts),
            'delete_url': reverse("%s:%s_%s_delete" % (
                self.admin_site.name, v_opts.app_label, v_opts.module_name), args=(quote(version.pk),)),
            'working_with_version': True,
            'has_children': version.revision.children.exists(),
            'is_recovering': recovering,
            'is_approved': is_approved,
            'is_rejected': is_rejected,
            'is_pending': is_pending,
            'moderator_old_comment': version.revision.comment,
        }

        context.update(extra_context or {})
        self.put_can_be_branched(request, object_id, context, version)
        self.put_content_permissions(request, context)
        return render_to_response(form_template, context, template.RequestContext(request))