Пример #1
0
 def get_context_data(self, **kwargs):
     context = super().get_context_data(**kwargs)
     context.update({
         'page':
         self.page,
         'page_for_status':
         self.page_for_status,
         'content_type':
         self.page_content_type,
         'edit_handler':
         self.edit_handler,
         'errors_debug':
         self.errors_debug,
         'action_menu':
         PageActionMenu(self.request, view='edit', page=self.page),
         'preview_modes':
         self.page.preview_modes,
         'form':
         self.form,
         'next':
         self.next_url,
         'has_unsaved_changes':
         self.has_unsaved_changes,
         'page_locked':
         self.page_perms.page_locked(),
         'workflow_state':
         self.workflow_state
         if self.workflow_state and self.workflow_state.is_active else None,
         'current_task_state':
         self.page.current_workflow_task_state,
         'publishing_will_cancel_workflow':
         self.workflow_tasks
         and getattr(settings, 'WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH', True)
     })
     return context
Пример #2
0
 def get_context_data(self, **kwargs):
     context = super().get_context_data(**kwargs)
     context.update({
         'content_type':
         self.page_content_type,
         'page_class':
         self.page_class,
         'parent_page':
         self.parent_page,
         'edit_handler':
         self.edit_handler,
         'action_menu':
         PageActionMenu(self.request,
                        view='create',
                        parent_page=self.parent_page),
         'preview_modes':
         self.page.preview_modes,
         'form':
         self.form,
         'next':
         self.next_url,
         'has_unsaved_changes':
         self.has_unsaved_changes,
     })
     return context
Пример #3
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_page_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=revision_page,
                                        request=request)
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.bind_to(form=form)

    user_avatar = render_to_string("wagtailadmin/shared/user_avatar.html",
                                   {"user": revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  "created_at": revision.created_at.strftime("%d %b %Y %H:%M"),
                  "user": user_avatar,
              }),
    )

    return TemplateResponse(
        request,
        "wagtailadmin/pages/edit.html",
        {
            "page":
            page,
            "revision":
            revision,
            "is_revision":
            True,
            "content_type":
            content_type,
            "edit_handler":
            edit_handler,
            "errors_debug":
            None,
            "action_menu":
            PageActionMenu(request, view="revisions_revert", page=page),
            "preview_modes":
            page.preview_modes,
            "form":
            form,  # Used in unit tests
        },
    )
Пример #4
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'page':
            self.page,
            'page_for_status':
            self.page_for_status,
            'content_type':
            self.page_content_type,
            'edit_handler':
            self.edit_handler,
            'errors_debug':
            self.errors_debug,
            'action_menu':
            PageActionMenu(self.request, view='edit', page=self.page),
            'preview_modes':
            self.page.preview_modes,
            'form':
            self.form,
            'next':
            self.next_url,
            'has_unsaved_changes':
            self.has_unsaved_changes,
            'page_locked':
            self.page_perms.page_locked(),
            'workflow_state':
            self.workflow_state
            if self.workflow_state and self.workflow_state.is_active else None,
            'current_task_state':
            self.page.current_workflow_task_state,
            'publishing_will_cancel_workflow':
            self.workflow_tasks
            and getattr(settings, 'WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH', True),
            'locale':
            None,
            'translations': [],
        })

        if getattr(settings, 'WAGTAIL_I18N_ENABLED', False):
            user_perms = UserPagePermissionsProxy(self.request.user)

            context.update({
                'locale':
                self.page.locale,
                'translations':
                [{
                    'locale':
                    translation.locale,
                    'url':
                    reverse('wagtailadmin_pages:edit', args=[translation.id]),
                } for translation in self.page.get_translations().only(
                    'id', 'locale').select_related('locale')
                 if user_perms.for_page(translation).can_edit()],
            })

        return context
Пример #5
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            "page":
            self.page,
            "page_for_status":
            self.page_for_status,
            "content_type":
            self.page_content_type,
            "edit_handler":
            self.edit_handler,
            "errors_debug":
            self.errors_debug,
            "action_menu":
            PageActionMenu(self.request, view="edit", page=self.page),
            "preview_modes":
            self.page.preview_modes,
            "form":
            self.form,
            "next":
            self.next_url,
            "has_unsaved_changes":
            self.has_unsaved_changes,
            "page_locked":
            self.page_perms.page_locked(),
            "workflow_state":
            self.workflow_state
            if self.workflow_state and self.workflow_state.is_active else None,
            "current_task_state":
            self.page.current_workflow_task_state,
            "publishing_will_cancel_workflow":
            self.workflow_tasks
            and getattr(settings, "WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH", True),
            "locale":
            None,
            "translations": [],
        })

        if getattr(settings, "WAGTAIL_I18N_ENABLED", False):
            user_perms = UserPagePermissionsProxy(self.request.user)

            context.update({
                "locale":
                self.page.locale,
                "translations":
                [{
                    "locale":
                    translation.locale,
                    "url":
                    reverse("wagtailadmin_pages:edit", args=[translation.id]),
                } for translation in self.page.get_translations().only(
                    "id", "locale", "depth").select_related("locale")
                 if user_perms.for_page(translation).can_edit()],
            })

        return context
Пример #6
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_page_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=revision_page,
                                        request=request)
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.bind_to(form=form)

    user_avatar = render_to_string('wagtailadmin/shared/user_avatar.html',
                                   {'user': revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  'created_at': revision.created_at.strftime("%d %b %Y %H:%M"),
                  'user': user_avatar,
              }))

    return TemplateResponse(
        request,
        'wagtailadmin/pages/edit.html',
        {
            'page':
            page,
            'revision':
            revision,
            'is_revision':
            True,
            'content_type':
            content_type,
            'edit_handler':
            edit_handler,
            'errors_debug':
            None,
            'action_menu':
            PageActionMenu(request, view='revisions_revert', page=page),
            'preview_modes':
            page.preview_modes,
            'form':
            form,  # Used in unit tests
        })
Пример #7
0
def update_page_from_import(request, page, parsed_doc):
    """
    Renders an edit page with the content of the page replaced with the content in the given document
    """
    page.update_from_import(parsed_doc, request.user)

    edit_handler = page.get_edit_handler()
    edit_handler = edit_handler.bind_to(request=request, instance=page)
    form_class = edit_handler.get_form_class()

    next_url = get_valid_next_url_from_request(request)

    form = form_class(instance=page)
    has_unsaved_changes = True

    edit_handler = edit_handler.bind_to(form=form)

    return render(
        request,
        "wagtailadmin/pages/edit.html",
        {
            "page":
            page,
            "page_for_status":
            page,
            "content_type":
            page.content_type,
            "edit_handler":
            edit_handler,
            "action_menu":
            PageActionMenu(
                request, view="edit", page=page,
                parent_page=page.get_parent()),
            "preview_modes":
            page.preview_modes,
            "form":
            form,
            "next":
            next_url,
            "has_unsaved_changes":
            has_unsaved_changes,
        },
    )
Пример #8
0
def create_page_from_import(request, parent_page, page_class, parsed_doc):
    """
    Renders a pre-populated create page based on a parsed document for a Page model with ContentImportMixin
    """

    page = page_class.create_from_import(parsed_doc, request.user)

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(request=request, instance=page)
    form_class = edit_handler.get_form_class()

    next_url = get_valid_next_url_from_request(request)

    form = form_class(instance=page, parent_page=parent_page)
    has_unsaved_changes = False

    edit_handler = edit_handler.bind_to(form=form)

    return render(
        request,
        "wagtailadmin/pages/create.html",
        {
            "content_type":
            page.content_type,
            "page_class":
            page_class,
            "parent_page":
            parent_page,
            "edit_handler":
            edit_handler,
            "action_menu":
            PageActionMenu(request, view="create", parent_page=parent_page),
            "preview_modes":
            page.preview_modes,
            "form":
            form,
            "next":
            next_url,
            "has_unsaved_changes":
            has_unsaved_changes,
        },
    )
Пример #9
0
def edit(request, page_id):
    real_page_record = get_object_or_404(Page, id=page_id)
    latest_revision = real_page_record.get_latest_revision()
    page = real_page_record.get_latest_revision_as_page()
    parent = page.get_parent()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    for fn in hooks.get_hooks('before_edit_page'):
        result = fn(request, page)
        if hasattr(result, 'status_code'):
            return result

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=page, request=request)
    form_class = edit_handler.get_form_class()

    next_url = get_valid_next_url_from_request(request)

    errors_debug = None

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES, instance=page,
                          parent_page=parent)

        if form.is_valid() and not page.locked:
            page = form.save(commit=False)

            is_publishing = bool(request.POST.get('action-publish')) and page_perms.can_publish()
            is_submitting = bool(request.POST.get('action-submit'))
            is_reverting = bool(request.POST.get('revision'))

            # If a revision ID was passed in the form, get that revision so its
            # date can be referenced in notification messages
            if is_reverting:
                previous_revision = get_object_or_404(page.revisions, id=request.POST.get('revision'))

            # Save revision
            revision = page.save_revision(
                user=request.user,
                submitted_for_moderation=is_submitting,
            )
            # store submitted go_live_at for messaging below
            go_live_at = page.go_live_at

            # Publish
            if is_publishing:
                revision.publish()
                # Need to reload the page because the URL may have changed, and we
                # need the up-to-date URL for the "View Live" button.
                page = page.specific_class.objects.get(pk=page.pk)

            # Notifications
            if is_publishing:
                if go_live_at and go_live_at > timezone.now():
                    # Page has been scheduled for publishing in the future

                    if is_reverting:
                        message = _(
                            "Revision from {0} of page '{1}' has been scheduled for publishing."
                        ).format(
                            previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                            page.get_admin_display_title()
                        )
                    else:
                        if page.live:
                            message = _(
                                "Page '{0}' is live and this revision has been scheduled for publishing."
                            ).format(
                                page.get_admin_display_title()
                            )
                        else:
                            message = _(
                                "Page '{0}' has been scheduled for publishing."
                            ).format(
                                page.get_admin_display_title()
                            )

                    messages.success(request, message, buttons=[
                        messages.button(
                            reverse('wagtailadmin_pages:edit', args=(page.id,)),
                            _('Edit')
                        )
                    ])

                else:
                    # Page is being published now

                    if is_reverting:
                        message = _(
                            "Revision from {0} of page '{1}' has been published."
                        ).format(
                            previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                            page.get_admin_display_title()
                        )
                    else:
                        message = _(
                            "Page '{0}' has been published."
                        ).format(
                            page.get_admin_display_title()
                        )

                    buttons = []
                    if page.url is not None:
                        buttons.append(messages.button(page.url, _('View live'), new_window=True))
                    buttons.append(messages.button(reverse('wagtailadmin_pages:edit', args=(page_id,)), _('Edit')))
                    messages.success(request, message, buttons=buttons)

            elif is_submitting:

                message = _(
                    "Page '{0}' has been submitted for moderation."
                ).format(
                    page.get_admin_display_title()
                )

                messages.success(request, message, buttons=[
                    messages.button(
                        reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                        _('View draft'),
                        new_window=True
                    ),
                    messages.button(
                        reverse('wagtailadmin_pages:edit', args=(page_id,)),
                        _('Edit')
                    )
                ])

                if not send_notification(page.get_latest_revision().id, 'submitted', request.user.pk):
                    messages.error(request, _("Failed to send notifications to moderators"))

            else:  # Saving

                if is_reverting:
                    message = _(
                        "Page '{0}' has been replaced with revision from {1}."
                    ).format(
                        page.get_admin_display_title(),
                        previous_revision.created_at.strftime("%d %b %Y %H:%M")
                    )
                else:
                    message = _(
                        "Page '{0}' has been updated."
                    ).format(
                        page.get_admin_display_title()
                    )

                messages.success(request, message)

            for fn in hooks.get_hooks('after_edit_page'):
                result = fn(request, page)
                if hasattr(result, 'status_code'):
                    return result

            if is_publishing or is_submitting:
                # we're done here - redirect back to the explorer
                if next_url:
                    # redirect back to 'next' url if present
                    return redirect(next_url)
                # redirect back to the explorer
                return redirect('wagtailadmin_explore', page.get_parent().id)
            else:
                # Just saving - remain on edit page for further edits
                target_url = reverse('wagtailadmin_pages:edit', args=[page.id])
                if next_url:
                    # Ensure the 'next' url is passed through again if present
                    target_url += '?next=%s' % urlquote(next_url)
                return redirect(target_url)
        else:
            if page.locked:
                messages.error(request, _("The page could not be saved as it is locked"))
            else:
                messages.validation_error(
                    request, _("The page could not be saved due to validation errors"), form
                )
            errors_debug = (
                repr(form.errors)
                + repr([
                    (name, formset.errors)
                    for (name, formset) in form.formsets.items()
                    if formset.errors
                ])
            )
            has_unsaved_changes = True
    else:
        form = form_class(instance=page, parent_page=parent)
        has_unsaved_changes = False

    edit_handler = edit_handler.bind_to(form=form)

    # Check for revisions still undergoing moderation and warn
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    if page.live and page.has_unpublished_changes:
        # Page status needs to present the version of the page containing the correct live URL
        page_for_status = real_page_record.specific
    else:
        page_for_status = page

    return render(request, 'wagtailadmin/pages/edit.html', {
        'page': page,
        'page_for_status': page_for_status,
        'content_type': content_type,
        'edit_handler': edit_handler,
        'errors_debug': errors_debug,
        'action_menu': PageActionMenu(request, view='edit', page=page),
        'preview_modes': page.preview_modes,
        'form': form,
        'next': next_url,
        'has_unsaved_changes': has_unsaved_changes,
    })
Пример #10
0
def create(request, content_type_app_name, content_type_model_name, parent_page_id):
    parent_page = get_object_or_404(Page, id=parent_page_id).specific
    parent_page_perms = parent_page.permissions_for_user(request.user)
    if not parent_page_perms.can_add_subpage():
        raise PermissionDenied

    try:
        content_type = ContentType.objects.get_by_natural_key(content_type_app_name, content_type_model_name)
    except ContentType.DoesNotExist:
        raise Http404

    # Get class
    page_class = content_type.model_class()

    # Make sure the class is a descendant of Page
    if not issubclass(page_class, Page):
        raise Http404

    # page must be in the list of allowed subpage types for this parent ID
    if page_class not in parent_page.creatable_subpage_models():
        raise PermissionDenied

    if not page_class.can_create_at(parent_page):
        raise PermissionDenied

    for fn in hooks.get_hooks('before_create_page'):
        result = fn(request, parent_page, page_class)
        if hasattr(result, 'status_code'):
            return result

    page = page_class(owner=request.user)
    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(request=request, instance=page)
    form_class = edit_handler.get_form_class()

    next_url = get_valid_next_url_from_request(request)

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES, instance=page,
                          parent_page=parent_page)

        if form.is_valid():
            page = form.save(commit=False)

            is_publishing = bool(request.POST.get('action-publish')) and parent_page_perms.can_publish_subpage()
            is_submitting = bool(request.POST.get('action-submit'))

            if not is_publishing:
                page.live = False

            # Save page
            parent_page.add_child(instance=page)

            # Save revision
            revision = page.save_revision(
                user=request.user,
                submitted_for_moderation=is_submitting,
            )

            # Publish
            if is_publishing:
                revision.publish()

            # Notifications
            if is_publishing:
                if page.go_live_at and page.go_live_at > timezone.now():
                    messages.success(request, _("Page '{0}' created and scheduled for publishing.").format(page.get_admin_display_title()), buttons=[
                        messages.button(reverse('wagtailadmin_pages:edit', args=(page.id,)), _('Edit'))
                    ])
                else:
                    buttons = []
                    if page.url is not None:
                        buttons.append(messages.button(page.url, _('View live'), new_window=True))
                    buttons.append(messages.button(reverse('wagtailadmin_pages:edit', args=(page.id,)), _('Edit')))
                    messages.success(request, _("Page '{0}' created and published.").format(page.get_admin_display_title()), buttons=buttons)
            elif is_submitting:
                messages.success(
                    request,
                    _("Page '{0}' created and submitted for moderation.").format(page.get_admin_display_title()),
                    buttons=[
                        messages.button(
                            reverse('wagtailadmin_pages:view_draft', args=(page.id,)),
                            _('View draft'),
                            new_window=True
                        ),
                        messages.button(
                            reverse('wagtailadmin_pages:edit', args=(page.id,)),
                            _('Edit')
                        )
                    ]
                )
                if not send_notification(page.get_latest_revision().id, 'submitted', request.user.pk):
                    messages.error(request, _("Failed to send notifications to moderators"))
            else:
                messages.success(request, _("Page '{0}' created.").format(page.get_admin_display_title()))

            for fn in hooks.get_hooks('after_create_page'):
                result = fn(request, page)
                if hasattr(result, 'status_code'):
                    return result

            if is_publishing or is_submitting:
                # we're done here
                if next_url:
                    # redirect back to 'next' url if present
                    return redirect(next_url)
                # redirect back to the explorer
                return redirect('wagtailadmin_explore', page.get_parent().id)
            else:
                # Just saving - remain on edit page for further edits
                target_url = reverse('wagtailadmin_pages:edit', args=[page.id])
                if next_url:
                    # Ensure the 'next' url is passed through again if present
                    target_url += '?next=%s' % urlquote(next_url)
                return redirect(target_url)
        else:
            messages.validation_error(
                request, _("The page could not be created due to validation errors"), form
            )
            has_unsaved_changes = True
    else:
        signals.init_new_page.send(sender=create, page=page, parent=parent_page)
        form = form_class(instance=page, parent_page=parent_page)
        has_unsaved_changes = False

    edit_handler = edit_handler.bind_to(form=form)

    return render(request, 'wagtailadmin/pages/create.html', {
        'content_type': content_type,
        'page_class': page_class,
        'parent_page': parent_page,
        'edit_handler': edit_handler,
        'action_menu': PageActionMenu(request, view='create', parent_page=parent_page),
        'preview_modes': page.preview_modes,
        'form': form,
        'next': next_url,
        'has_unsaved_changes': has_unsaved_changes,
    })
Пример #11
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        bound_panel = self.edit_handler.get_bound_panel(request=self.request,
                                                        instance=self.page,
                                                        form=self.form)
        action_menu = PageActionMenu(self.request,
                                     view="create",
                                     parent_page=self.parent_page)

        context.update({
            "content_type":
            self.page_content_type,
            "page_class":
            self.page_class,
            "parent_page":
            self.parent_page,
            "edit_handler":
            bound_panel,
            "action_menu":
            action_menu,
            "preview_modes":
            self.page.preview_modes,
            "form":
            self.form,
            "next":
            self.next_url,
            "has_unsaved_changes":
            self.has_unsaved_changes,
            "locale":
            None,
            "translations": [],
            "media":
            bound_panel.media + self.form.media + action_menu.media,
        })

        if getattr(settings, "WAGTAIL_I18N_ENABLED", False):
            # Pages can be created in any language at the root level
            if self.parent_page.is_root():
                translations = [{
                    "locale":
                    locale,
                    "url":
                    reverse(
                        "wagtailadmin_pages:add",
                        args=[
                            self.page_content_type.app_label,
                            self.page_content_type.model,
                            self.parent_page.id,
                        ],
                    ) + "?" + urlencode({"locale": locale.language_code}),
                } for locale in Locale.objects.all()]

            else:
                user_perms = UserPagePermissionsProxy(self.request.user)
                translations = [
                    {
                        "locale":
                        translation.locale,
                        "url":
                        reverse(
                            "wagtailadmin_pages:add",
                            args=[
                                self.page_content_type.app_label,
                                self.page_content_type.model,
                                translation.id,
                            ],
                        ),
                    } for translation in self.parent_page.get_translations(
                    ).only("id", "locale").select_related("locale")
                    if user_perms.for_page(translation).can_add_subpage()
                    and self.page_class in
                    translation.specific_class.creatable_subpage_models()
                    and self.page_class.can_create_at(translation)
                ]

            context.update({
                "locale": self.locale,
                "translations": translations,
            })

        return context
Пример #12
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({
            'content_type':
            self.page_content_type,
            'page_class':
            self.page_class,
            'parent_page':
            self.parent_page,
            'edit_handler':
            self.edit_handler,
            'action_menu':
            PageActionMenu(self.request,
                           view='create',
                           parent_page=self.parent_page),
            'preview_modes':
            self.page.preview_modes,
            'form':
            self.form,
            'next':
            self.next_url,
            'has_unsaved_changes':
            self.has_unsaved_changes,
            'locale':
            None,
            'translations': [],
        })

        if getattr(settings, 'WAGTAIL_I18N_ENABLED', False):
            # Pages can be created in any language at the root level
            if self.parent_page.is_root():
                translations = [{
                    'locale':
                    locale,
                    'url':
                    reverse(
                        'wagtailadmin_pages:add',
                        args=[
                            self.page_content_type.app_label,
                            self.page_content_type.model, self.parent_page.id
                        ]) + '?' + urlencode({'locale': locale.language_code}),
                } for locale in Locale.objects.all()]

            else:
                user_perms = UserPagePermissionsProxy(self.request.user)
                translations = [
                    {
                        'locale':
                        translation.locale,
                        'url':
                        reverse('wagtailadmin_pages:add',
                                args=[
                                    self.page_content_type.app_label,
                                    self.page_content_type.model,
                                    translation.id
                                ]),
                    } for translation in self.parent_page.get_translations(
                    ).only('id', 'locale').select_related('locale')
                    if user_perms.for_page(translation).can_add_subpage()
                    and self.page_class in
                    translation.specific_class.creatable_subpage_models()
                    and self.page_class.can_create_at(translation)
                ]

            context.update({
                'locale': self.locale,
                'translations': translations,
            })

        return context
Пример #13
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        bound_panel = self.edit_handler.get_bound_panel(instance=self.page,
                                                        request=self.request,
                                                        form=self.form)
        action_menu = PageActionMenu(
            self.request,
            view="edit",
            page=self.page,
            lock=self.lock,
            locked_for_user=self.locked_for_user,
        )
        side_panels = PageSidePanels(
            self.request,
            self.page_for_status,
            preview_enabled=True,
            comments_enabled=self.form.show_comments_toggle,
        )

        context.update({
            "page":
            self.page,
            "page_for_status":
            self.page_for_status,
            "content_type":
            self.page_content_type,
            "edit_handler":
            bound_panel,
            "errors_debug":
            self.errors_debug,
            "action_menu":
            action_menu,
            "side_panels":
            side_panels,
            "form":
            self.form,
            "next":
            self.next_url,
            "has_unsaved_changes":
            self.has_unsaved_changes,
            "page_locked":
            self.locked_for_user,
            "workflow_state":
            self.workflow_state
            if self.workflow_state and self.workflow_state.is_active else None,
            "current_task_state":
            self.page.current_workflow_task_state,
            "publishing_will_cancel_workflow":
            self.workflow_tasks
            and getattr(settings, "WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH", True),
            "locale":
            None,
            "translations": [],
            "media":
            bound_panel.media + self.form.media + action_menu.media +
            side_panels.media,
        })

        if getattr(settings, "WAGTAIL_I18N_ENABLED", False):
            user_perms = UserPagePermissionsProxy(self.request.user)

            context.update({
                "locale":
                self.page.locale,
                "translations":
                [{
                    "locale":
                    translation.locale,
                    "url":
                    reverse("wagtailadmin_pages:edit", args=[translation.id]),
                } for translation in self.page.get_translations().only(
                    "id", "locale", "depth").select_related("locale")
                 if user_perms.for_page(translation).can_edit()],
            })

        return context
Пример #14
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.get_bound_panel(instance=revision_page,
                                                request=request,
                                                form=form)

    lock = page.get_lock()

    action_menu = PageActionMenu(
        request,
        view="revisions_revert",
        page=page,
        lock=lock,
        locked_for_user=lock is not None and lock.for_user(request.user),
    )
    side_panels = PageSidePanels(
        request,
        page,
        preview_enabled=True,
        comments_enabled=form.show_comments_toggle,
    )

    user_avatar = render_to_string("wagtailadmin/shared/user_avatar.html",
                                   {"user": revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  "created_at": revision.created_at.strftime("%d %b %Y %H:%M"),
                  "user": user_avatar,
              }),
    )

    return TemplateResponse(
        request,
        "wagtailadmin/pages/edit.html",
        {
            "page":
            page,
            "revision":
            revision,
            "is_revision":
            True,
            "content_type":
            content_type,
            "edit_handler":
            edit_handler,
            "errors_debug":
            None,
            "action_menu":
            action_menu,
            "side_panels":
            side_panels,
            "form":
            form,  # Used in unit tests
            "media":
            edit_handler.media + form.media + action_menu.media +
            side_panels.media,
        },
    )
Пример #15
0
def edit(request, page_id):
    real_page_record = get_object_or_404(Page, id=page_id)
    latest_revision = real_page_record.get_latest_revision()
    content_type = real_page_record.cached_content_type
    page_class = real_page_record.specific_class

    if page_class is None:
        raise PageClassNotFoundError(
            f"The page '{real_page_record}' cannot be edited because the "
            f"model class used to create it ({content_type.app_label}."
            f"{content_type.model}) can no longer be found in the codebase. "
            "This usually happens as a result of switching between git "
            "branches without running migrations to trigger the removal of "
            "unused ContentTypes. To edit the page, you will need to switch "
            "back to a branch where the model class is still present."
        )

    page = real_page_record.get_latest_revision_as_page()
    parent = page.get_parent()

    page_perms = page.permissions_for_user(request.user)

    if not page_perms.can_edit():
        raise PermissionDenied

    next_url = get_valid_next_url_from_request(request)

    for fn in hooks.get_hooks('before_edit_page'):
        result = fn(request, page)
        if hasattr(result, 'status_code'):
            return result

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=page, request=request)
    form_class = edit_handler.get_form_class()

    if request.method == 'GET':
        if page_perms.user_has_lock():
            if page.locked_at:
                lock_message = format_html(_("<b>Page '{}' was locked</b> by <b>you</b> on <b>{}</b>."), page.get_admin_display_title(), page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                lock_message = format_html(_("<b>Page '{}' is locked</b> by <b>you</b>."), page.get_admin_display_title())

            lock_message += format_html(
                '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                reverse('wagtailadmin_pages:unlock', args=(page.id,)),
                _("Unlock")
            )
            messages.warning(request, lock_message, extra_tags='lock')

        elif page.locked and page_perms.page_locked():
            # the page can also be locked at a permissions level if in a workflow, on a task the user is not a reviewer for
            # this should be indicated separately
            if page.locked_by and page.locked_at:
                lock_message = format_html(_("<b>Page '{}' was locked</b> by <b>{}</b> on <b>{}</b>."), page.get_admin_display_title(), str(page.locked_by), page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                # Page was probably locked with an old version of Wagtail, or a script
                lock_message = format_html(_("<b>Page '{}' is locked</b>."), page.get_admin_display_title())

            if page_perms.can_unlock():
                lock_message += format_html(
                    '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                    reverse('wagtailadmin_pages:unlock', args=(page.id,)),
                    _("Unlock")
                )
            messages.error(request, lock_message, extra_tags='lock')

        if page.current_workflow_state:
            workflow_state = page.current_workflow_state
            workflow = workflow_state.workflow
            workflow_tasks = workflow_state.all_tasks_with_status()
            task = workflow_state.current_task_state.task
            if (
                workflow_state.status != WorkflowState.STATUS_NEEDS_CHANGES
                and task.specific.page_locked_for_user(page, request.user)
            ):
                # Check for revisions still undergoing moderation and warn
                if len(workflow_tasks) == 1:
                    # If only one task in workflow, show simple message
                    workflow_info = _("This page is currently awaiting moderation.")
                else:
                    workflow_info = format_html(
                        _("This page is awaiting <b>'{}'</b> in the <b>'{}'</b> workflow."),
                        task.name, workflow.name
                    )
                messages.error(request, mark_safe(workflow_info + " " + _("Only reviewers for this task can edit the page.")),
                               extra_tags="lock")
    # Check for revisions still undergoing moderation and warn - this is for the old moderation system
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    # Show current workflow state if set, default to last workflow state
    workflow_state = page.current_workflow_state or page.workflow_states.order_by('created_at').last()
    if workflow_state:
        workflow_tasks = workflow_state.all_tasks_with_status()
    else:
        workflow_tasks = []

    errors_debug = None

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES, instance=page,
                          parent_page=parent)

        is_publishing = False
        is_submitting = False
        is_restarting_workflow = False
        is_reverting = False
        is_saving = False
        is_cancelling_workflow = bool(request.POST.get('action-cancel-workflow')) and workflow_state and workflow_state.user_can_cancel(request.user)
        if is_cancelling_workflow:
            workflow_state.cancel(user=request.user)
            # do this here so even if the page is locked due to not having permissions, the original submitter can still cancel the workflow

        if form.is_valid() and not page_perms.page_locked():
            page = form.save(commit=False)

            is_publishing = bool(request.POST.get('action-publish')) and page_perms.can_publish()
            is_submitting = bool(request.POST.get('action-submit')) and page_perms.can_submit_for_moderation()
            is_restarting_workflow = bool(request.POST.get('action-restart-workflow')) and page_perms.can_submit_for_moderation() and workflow_state and workflow_state.user_can_cancel(request.user)
            is_reverting = bool(request.POST.get('revision'))

            is_performing_workflow_action = bool(request.POST.get('action-workflow-action'))
            if is_performing_workflow_action:
                workflow_action = request.POST['workflow-action-name']
                available_actions = page.current_workflow_task.get_actions(page, request.user)
                available_action_names = [name for name, verbose_name, modal in available_actions]
                if workflow_action not in available_action_names:
                    # prevent this action
                    is_performing_workflow_action = False

            is_saving = True
            has_content_changes = form.has_changed()

            if is_restarting_workflow:
                workflow_state.cancel(user=request.user)

            # If a revision ID was passed in the form, get that revision so its
            # date can be referenced in notification messages
            if is_reverting:
                previous_revision = get_object_or_404(page.revisions, id=request.POST.get('revision'))

            if is_performing_workflow_action and not has_content_changes:
                # don't save a new revision, as we're just going to update the page's
                # workflow state with no content changes
                revision = latest_revision
            else:
                # Save revision
                revision = page.save_revision(
                    user=request.user,
                    log_action=True,  # Always log the new revision on edit
                    previous_revision=(previous_revision if is_reverting else None)
                )

            # store submitted go_live_at for messaging below
            go_live_at = page.go_live_at

            # Publish
            if is_publishing:
                for fn in hooks.get_hooks('before_publish_page'):
                    result = fn(request, page)
                    if hasattr(result, 'status_code'):
                        return result

                revision.publish(
                    user=request.user,
                    changed=has_content_changes,
                    previous_revision=(previous_revision if is_reverting else None)
                )

                # Need to reload the page because the URL may have changed, and we
                # need the up-to-date URL for the "View Live" button.
                page = page.specific_class.objects.get(pk=page.pk)

                for fn in hooks.get_hooks('after_publish_page'):
                    result = fn(request, page)
                    if hasattr(result, 'status_code'):
                        return result

            # Submit
            if is_submitting or is_restarting_workflow:
                if workflow_state and workflow_state.status == WorkflowState.STATUS_NEEDS_CHANGES:
                    # If the workflow was in the needs changes state, resume the existing workflow on submission
                    workflow_state.resume(request.user)
                else:
                    # Otherwise start a new workflow
                    workflow = page.get_workflow()
                    workflow.start(page, request.user)

            if is_performing_workflow_action:
                extra_workflow_data_json = request.POST.get('workflow-action-extra-data', '{}')
                extra_workflow_data = json.loads(extra_workflow_data_json)
                page.current_workflow_task.on_action(page.current_workflow_task_state, request.user, workflow_action, **extra_workflow_data)

        # Notifications
        if is_publishing:
            if go_live_at and go_live_at > timezone.now():
                # Page has been scheduled for publishing in the future

                if is_reverting:
                    message = _(
                        "Version from {0} of page '{1}' has been scheduled for publishing."
                    ).format(
                        previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                        page.get_admin_display_title()
                    )
                else:
                    if page.live:
                        message = _(
                            "Page '{0}' is live and this version has been scheduled for publishing."
                        ).format(
                            page.get_admin_display_title()
                        )

                    else:
                        message = _(
                            "Page '{0}' has been scheduled for publishing."
                        ).format(
                            page.get_admin_display_title()
                        )

                messages.success(request, message, buttons=[
                    messages.button(
                        reverse('wagtailadmin_pages:edit', args=(page.id,)),
                        _('Edit')
                    )
                ])

            else:
                # Page is being published now

                if is_reverting:
                    message = _(
                        "Version from {0} of page '{1}' has been published."
                    ).format(
                        previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                        page.get_admin_display_title()
                    )
                else:
                    message = _(
                        "Page '{0}' has been published."
                    ).format(
                        page.get_admin_display_title()
                    )

                buttons = []
                if page.url is not None:
                    buttons.append(messages.button(page.url, _('View live'), new_window=True))
                buttons.append(messages.button(reverse('wagtailadmin_pages:edit', args=(page_id,)), _('Edit')))
                messages.success(request, message, buttons=buttons)

        elif is_submitting:

            message = _(
                "Page '{0}' has been submitted for moderation."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    _('Edit')
                )
            ])

        elif is_cancelling_workflow:
            message = _(
                "Workflow on page '{0}' has been cancelled."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    ('Edit')
                )
            ])

        elif is_restarting_workflow:

            message = _(
                "Workflow on page '{0}' has been restarted."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    _('Edit')
                )
            ])

        elif is_reverting:
            message = _(
                "Page '{0}' has been replaced with version from {1}."
            ).format(
                page.get_admin_display_title(),
                previous_revision.created_at.strftime("%d %b %Y %H:%M")
            )

            messages.success(request, message)
        elif is_saving:
            message = _(
                "Page '{0}' has been updated."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message)

        if is_saving:
            for fn in hooks.get_hooks('after_edit_page'):
                result = fn(request, page)
                if hasattr(result, 'status_code'):
                    return result

            if is_publishing or is_submitting or is_restarting_workflow or is_performing_workflow_action:
                # we're done here - redirect back to the explorer
                if next_url:
                    # redirect back to 'next' url if present
                    return redirect(next_url)
                # redirect back to the explorer
                return redirect('wagtailadmin_explore', page.get_parent().id)
            else:
                # Just saving - remain on edit page for further edits
                target_url = reverse('wagtailadmin_pages:edit', args=[page.id])
                if next_url:
                    # Ensure the 'next' url is passed through again if present
                    target_url += '?next=%s' % urlquote(next_url)
                return redirect(target_url)
        else:
            if page_perms.page_locked():
                messages.error(request, _("The page could not be saved as it is locked"))
            else:
                messages.validation_error(
                    request, _("The page could not be saved due to validation errors"), form
                )
            errors_debug = (
                repr(form.errors)
                + repr([
                    (name, formset.errors)
                    for (name, formset) in form.formsets.items()
                    if formset.errors
                ])
            )
            has_unsaved_changes = True
    else:
        form = form_class(instance=page, parent_page=parent)
        has_unsaved_changes = False

    edit_handler = edit_handler.bind_to(form=form)

    # Check for revisions still undergoing moderation and warn
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    if page.live and page.has_unpublished_changes:
        # Page status needs to present the version of the page containing the correct live URL
        page_for_status = real_page_record.specific
    else:
        page_for_status = page

    return TemplateResponse(request, 'wagtailadmin/pages/edit.html', {
        'page': page,
        'page_for_status': page_for_status,
        'content_type': content_type,
        'edit_handler': edit_handler,
        'errors_debug': errors_debug,
        'action_menu': PageActionMenu(request, view='edit', page=page),
        'preview_modes': page.preview_modes,
        'form': form,
        'next': next_url,
        'has_unsaved_changes': has_unsaved_changes,
        'page_locked': page_perms.page_locked(),
        'workflow_state': workflow_state if workflow_state and workflow_state.is_active else None,
        'current_task_state': page.current_workflow_task_state,
        'publishing_will_cancel_workflow': workflow_tasks and getattr(settings, 'WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH', True)
    })