from django.shortcuts import redirect from django.template.response import TemplateResponse from django.utils.translation import gettext as _ from wagtail import hooks from wagtail.actions.copy_page import CopyPageAction from wagtail.actions.create_alias import CreatePageAliasAction from wagtail.admin import messages from wagtail.admin.auth import user_has_any_page_permission, user_passes_test from wagtail.admin.forms.pages import CopyForm from wagtail.admin.utils import get_valid_next_url_from_request from wagtail.models import Page @user_passes_test(user_has_any_page_permission) def copy(request, page_id): page = Page.objects.get(id=page_id) # Parent page defaults to parent of source page parent_page = page.get_parent() # Check if the user has permission to publish subpages on the parent can_publish = parent_page.permissions_for_user(request.user).can_publish_subpage() form_class = getattr(page.specific_class, "copy_form_class", CopyForm) form = form_class( request.POST or None, user=request.user, page=page, can_publish=can_publish ) next_url = get_valid_next_url_from_request(request) for fn in hooks.get_hooks("before_copy_page"): result = fn(request, page) if hasattr(result, "status_code"): return result # Check if user is submitting if request.method == "POST": # Prefill parent_page in case the form is invalid (as prepopulated value for the form field, # because ModelChoiceField seems to not fall back to the user given value) parent_page = Page.objects.get(id=request.POST["new_parent_page"]) if form.is_valid(): # Receive the parent page (this should never be empty) if form.cleaned_data["new_parent_page"]: parent_page = form.cleaned_data["new_parent_page"] # Re-check if the user has permission to publish subpages on the new parent can_publish = parent_page.permissions_for_user( request.user ).can_publish_subpage() keep_live = can_publish and form.cleaned_data.get("publish_copies") # Copy the page # Note that only users who can publish in the new parent page can create an alias. # This is because alias pages must always match their original page's state. if can_publish and form.cleaned_data.get("alias"): action = CreatePageAliasAction( page.specific, recursive=form.cleaned_data.get("copy_subpages"), parent=parent_page, update_slug=form.cleaned_data["new_slug"], user=request.user, ) new_page = action.execute(skip_permission_checks=True) else: action = CopyPageAction( page=page, recursive=form.cleaned_data.get("copy_subpages"), to=parent_page, update_attrs={ "title": form.cleaned_data["new_title"], "slug": form.cleaned_data["new_slug"], }, keep_live=keep_live, user=request.user, ) new_page = action.execute() # Give a success message back to the user if form.cleaned_data.get("copy_subpages"): messages.success( request, _("Page '%(page_title)s' and %(subpages_count)s subpages copied.") % { "page_title": page.specific_deferred.get_admin_display_title(), "subpages_count": new_page.get_descendants().count(), }, ) else: messages.success( request, _("Page '%(page_title)s' copied.") % {"page_title": page.specific_deferred.get_admin_display_title()}, ) for fn in hooks.get_hooks("after_copy_page"): result = fn(request, page, new_page) if hasattr(result, "status_code"): return result # Redirect to explore of parent page if next_url: return redirect(next_url) return redirect("wagtailadmin_explore", parent_page.id) return TemplateResponse( request, "wagtailadmin/pages/copy.html", { "page": page, "form": form, "next": next_url, }, )