コード例 #1
0
ファイル: documents.py プロジェクト: waffle-iron/tuiuiu.io
def add(request):
    Document = get_document_model()
    DocumentForm = get_document_form(Document)

    if request.method == 'POST':
        doc = Document(uploaded_by_user=request.user)
        form = DocumentForm(request.POST,
                            request.FILES,
                            instance=doc,
                            user=request.user)
        if form.is_valid():
            form.save()

            # Reindex the document to make sure all tags are indexed
            search_index.insert_or_update_object(doc)

            messages.success(request,
                             _("Document '{0}' added.").format(doc.title),
                             buttons=[
                                 messages.button(
                                     reverse('tuiuiudocs:edit',
                                             args=(doc.id, )), _('Edit'))
                             ])
            return redirect('tuiuiudocs:index')
        else:
            messages.error(request,
                           _("The document could not be saved due to errors."))
    else:
        form = DocumentForm(user=request.user)

    return render(request, "tuiuiudocs/documents/add.html", {
        'form': form,
    })
コード例 #2
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
def delete(request, page_id):
    page = get_object_or_404(Page, id=page_id)
    if not page.permissions_for_user(request.user).can_delete():
        raise PermissionDenied

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

    next_url = get_valid_next_url_from_request(request)

    if request.method == 'POST':
        parent_id = page.get_parent().id
        page.delete()

        messages.success(
            request,
            _("Page '{0}' deleted.").format(page.get_admin_display_title()))

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

        if next_url:
            return redirect(next_url)
        return redirect('tuiuiuadmin_explore', parent_id)

    return render(
        request, 'tuiuiuadmin/pages/confirm_delete.html', {
            'page': page,
            'descendant_count': page.get_descendant_count(),
            'next': next_url,
        })
コード例 #3
0
def index(request):

    form = SearchForm(placeholder=_("Search something"))

    example_form = ExampleForm()

    messages.success(request,
                     _("Success message"),
                     buttons=[
                         messages.button('', _('View live')),
                         messages.button('', _('Edit'))
                     ])
    messages.warning(request,
                     _("Warning message"),
                     buttons=[
                         messages.button('', _('View live')),
                         messages.button('', _('Edit'))
                     ])
    messages.error(request,
                   _("Error message"),
                   buttons=[
                       messages.button('', _('View live')),
                       messages.button('', _('Edit'))
                   ])

    paginator = Paginator(list(range(100)), 10)
    page = paginator.page(2)

    return render(request, 'styleguide/base.html', {
        'search_form': form,
        'example_form': example_form,
        'example_page': page,
    })
コード例 #4
0
ファイル: views.py プロジェクト: waffle-iron/tuiuiu.io
def edit(request, redirect_id):
    theredirect = get_object_or_404(models.Redirect, id=redirect_id)

    if not permission_policy.user_has_permission_for_instance(
        request.user, 'change', theredirect
    ):
        return permission_denied(request)

    if request.method == 'POST':
        form = RedirectForm(request.POST, request.FILES, instance=theredirect)
        if form.is_valid():
            form.save()
            messages.success(request, _("Redirect '{0}' updated.").format(theredirect.title), buttons=[
                messages.button(reverse('tuiuiuredirects:edit', args=(theredirect.id,)), _('Edit'))
            ])
            return redirect('tuiuiuredirects:index')
        else:
            messages.error(request, _("The redirect could not be saved due to errors."))
    else:
        form = RedirectForm(instance=theredirect)

    return render(request, "tuiuiuredirects/edit.html", {
        'redirect': theredirect,
        'form': form,
        'user_can_delete': permission_policy.user_has_permission(request.user, 'delete'),
    })
コード例 #5
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
def move_confirm(request, page_to_move_id, destination_id):
    page_to_move = get_object_or_404(Page, id=page_to_move_id).specific
    destination = get_object_or_404(Page, id=destination_id)
    if not page_to_move.permissions_for_user(
            request.user).can_move_to(destination):
        raise PermissionDenied

    if request.method == 'POST':
        # any invalid moves *should* be caught by the permission check above,
        # so don't bother to catch InvalidMoveToDescendant
        page_to_move.move(destination, pos='last-child')

        messages.success(request,
                         _("Page '{0}' moved.").format(
                             page_to_move.get_admin_display_title()),
                         buttons=[
                             messages.button(
                                 reverse('tuiuiuadmin_pages:edit',
                                         args=(page_to_move.id, )), _('Edit'))
                         ])

        return redirect('tuiuiuadmin_explore', destination.id)

    return render(request, 'tuiuiuadmin/pages/confirm_move.html', {
        'page_to_move': page_to_move,
        'destination': destination,
    })
コード例 #6
0
ファイル: views.py プロジェクト: waffle-iron/tuiuiu.io
def delete_submissions(request, page_id):
    if not get_forms_for_user(request.user).filter(id=page_id).exists():
        raise PermissionDenied

    page = get_object_or_404(Page, id=page_id).specific

    # Get submissions
    submission_ids = request.GET.getlist('selected-submissions')
    submissions = page.get_submission_class()._default_manager.filter(
        id__in=submission_ids)

    if request.method == 'POST':
        count = submissions.count()
        submissions.delete()

        messages.success(
            request,
            ungettext("One submission has been deleted.",
                      "%(count)d submissions have been deleted.", count) % {
                          'count': count,
                      })

        return redirect('tuiuiuforms:list_submissions', page_id)

    return render(request, 'tuiuiuforms/confirm_delete.html', {
        'page': page,
        'submissions': submissions,
    })
コード例 #7
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
def reject_moderation(request, revision_id):
    revision = get_object_or_404(PageRevision, id=revision_id)
    if not revision.page.permissions_for_user(request.user).can_publish():
        raise PermissionDenied

    if not revision.submitted_for_moderation:
        messages.error(
            request,
            _("The page '{0}' is not currently awaiting moderation.").format(
                revision.page.get_admin_display_title()))
        return redirect('tuiuiuadmin_home')

    if request.method == 'POST':
        revision.reject_moderation()
        messages.success(request,
                         _("Page '{0}' rejected for publication.").format(
                             revision.page.get_admin_display_title()),
                         buttons=[
                             messages.button(
                                 reverse('tuiuiuadmin_pages:edit',
                                         args=(revision.page.id, )), _('Edit'))
                         ])
        if not send_notification(revision.id, 'rejected', request.user.pk):
            messages.error(request,
                           _("Failed to send rejection notifications"))

    return redirect('tuiuiuadmin_home')
コード例 #8
0
def edit(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    can_delete = user_can_delete_user(request.user, user)

    if request.method == 'POST':
        form = get_user_edit_form()(request.POST, request.FILES, instance=user)
        if form.is_valid():
            user = form.save()
            messages.success(request,
                             _("User '{0}' updated.").format(user),
                             buttons=[
                                 messages.button(
                                     reverse('tuiuiuusers_users:edit',
                                             args=(user.pk, )), _('Edit'))
                             ])
            return redirect('tuiuiuusers_users:index')
        else:
            messages.error(request,
                           _("The user could not be saved due to errors."))
    else:
        form = get_user_edit_form()(instance=user)

    return render(request, 'tuiuiuusers/users/edit.html', {
        'user': user,
        'form': form,
        'can_delete': can_delete,
    })
コード例 #9
0
 def form_valid(self, form):
     self.form = form
     self.object = self.save_instance()
     success_message = self.get_success_message(self.object)
     if success_message is not None:
         messages.success(self.request, success_message, buttons=[
             messages.button(reverse(self.edit_url_name, args=(self.object.id,)), _('Edit'))
         ])
     return redirect(self.get_success_url())
コード例 #10
0
def delete(request, query_id):
    query = get_object_or_404(Query, id=query_id)

    if request.method == 'POST':
        query.editors_picks.all().delete()
        messages.success(request, _("Editor's picks deleted."))
        return redirect('searchpromotions:index')

    return render(request, 'searchpromotions/confirm_delete.html', {
        'query': query,
    })
コード例 #11
0
ファイル: groups.py プロジェクト: waffle-iron/tuiuiu.io
def delete(request, group_id):
    group = get_object_or_404(Group, id=group_id)

    if request.method == 'POST':
        group.delete()
        messages.success(request, _("Group '{0}' deleted.").format(group.name))
        return redirect('tuiuiuusers_groups:index')

    return render(request, "tuiuiuusers/groups/confirm_delete.html", {
        'group': group,
    })
コード例 #12
0
ファイル: collections.py プロジェクト: waffle-iron/tuiuiu.io
    def post(self, request, instance_id):
        self.instance = get_object_or_404(self.get_queryset(), id=instance_id)
        collection_contents = self.get_collection_contents()

        if collection_contents:
            # collection is non-empty; refuse to delete it
            return HttpResponseForbidden()

        self.instance.delete()
        messages.success(request, self.success_message.format(self.instance))
        return redirect(self.index_url_name)
コード例 #13
0
def delete(request, user_id):
    user = get_object_or_404(User, pk=user_id)

    if not user_can_delete_user(request.user, user):
        return permission_denied(request)

    if request.method == 'POST':
        user.delete()
        messages.success(request, _("User '{0}' deleted.").format(user))
        return redirect('tuiuiuusers_users:index')

    return render(request, "tuiuiuusers/users/confirm_delete.html", {
        'user': user,
    })
コード例 #14
0
def select_winner(request, experiment_id, variation_id):
    if not request.user.has_perm('experiments.change_experiment'):
        raise PermissionDenied
    experiment = get_object_or_404(Experiment, pk=experiment_id)
    variation = get_object_or_404(Page, pk=variation_id)

    if request.method == 'POST':
        experiment.select_winner(variation)

        messages.success(
            request,
            _("Page '{0}' has been selected as the winning variation.").format(variation.title),
        )

    return redirect('experiments:report', experiment.pk)
コード例 #15
0
def edit(request, query_id):
    query = get_object_or_404(Query, id=query_id)

    if request.method == 'POST':
        # Get query
        query_form = search_forms.QueryForm(request.POST)
        # and the recommendations
        searchpicks_formset = forms.SearchPromotionsFormSet(request.POST,
                                                            instance=query)

        if query_form.is_valid():
            new_query = Query.get(query_form['query_string'].value())

            # Save search picks
            if save_searchpicks(query, new_query, searchpicks_formset):
                messages.success(
                    request,
                    _("Editor's picks for '{0}' updated.").format(new_query),
                    buttons=[
                        messages.button(
                            reverse('searchpromotions:edit',
                                    args=(query.id, )), _('Edit'))
                    ])
                return redirect('searchpromotions:index')
            else:
                if len(searchpicks_formset.non_form_errors()):
                    messages.error(
                        request,
                        " ".join(error for error in
                                 searchpicks_formset.non_form_errors()))
                    # formset level error (e.g. no forms submitted)
                else:
                    messages.error(
                        request,
                        _("Recommendations have not been saved due to errors"))
                    # specific errors will be displayed within form fields

    else:
        query_form = search_forms.QueryForm(initial=dict(
            query_string=query.query_string))
        searchpicks_formset = forms.SearchPromotionsFormSet(instance=query)

    return render(
        request, 'searchpromotions/edit.html', {
            'query_form': query_form,
            'searchpicks_formset': searchpicks_formset,
            'query': query,
        })
コード例 #16
0
def edit(request, app_name, model_name, site_pk):
    model = get_model_from_url_params(app_name, model_name)
    if not user_can_edit_setting_type(request.user, model):
        raise PermissionDenied
    site = get_object_or_404(Site, pk=site_pk)

    setting_type_name = model._meta.verbose_name

    instance = model.for_site(site)
    edit_handler_class = get_setting_edit_handler(model)
    form_class = edit_handler_class.get_form_class(model)

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

        if form.is_valid():
            form.save()

            messages.success(
                request,
                _("{setting_type} updated.").format(
                    setting_type=capfirst(setting_type_name),
                    instance=instance))
            return redirect('settings:edit', app_name, model_name, site.pk)
        else:
            messages.error(request,
                           _("The setting could not be saved due to errors."))
            edit_handler = edit_handler_class(instance=instance, form=form)
    else:
        form = form_class(instance=instance)
        edit_handler = edit_handler_class(instance=instance, form=form)

    # Show a site switcher form if there are multiple sites
    site_switcher = None
    if Site.objects.count() > 1:
        site_switcher = SiteSwitchForm(site, model)

    return render(
        request, 'settings/edit.html', {
            'opts': model._meta,
            'setting_type_name': setting_type_name,
            'instance': instance,
            'edit_handler': edit_handler,
            'form': form,
            'site': site,
            'site_switcher': site_switcher,
            'tabbed': edit_handler_class.__name__ == '_TabbedInterface',
        })
コード例 #17
0
ファイル: views.py プロジェクト: waffle-iron/tuiuiu.io
def delete(request, redirect_id):
    theredirect = get_object_or_404(models.Redirect, id=redirect_id)

    if not permission_policy.user_has_permission_for_instance(
        request.user, 'delete', theredirect
    ):
        return permission_denied(request)

    if request.method == 'POST':
        theredirect.delete()
        messages.success(request, _("Redirect '{0}' deleted.").format(theredirect.title))
        return redirect('tuiuiuredirects:index')

    return render(request, "tuiuiuredirects/confirm_delete.html", {
        'redirect': theredirect,
    })
コード例 #18
0
def delete(request, image_id):
    image = get_object_or_404(get_image_model(), id=image_id)

    if not permission_policy.user_has_permission_for_instance(
            request.user, 'delete', image):
        return permission_denied(request)

    if request.method == 'POST':
        image.delete()
        messages.success(request,
                         _("Image '{0}' deleted.").format(image.title))
        return redirect('tuiuiuimages:index')

    return render(request, "tuiuiuimages/images/confirm_delete.html", {
        'image': image,
    })
コード例 #19
0
ファイル: documents.py プロジェクト: waffle-iron/tuiuiu.io
def delete(request, document_id):
    Document = get_document_model()
    doc = get_object_or_404(Document, id=document_id)

    if not permission_policy.user_has_permission_for_instance(
            request.user, 'delete', doc):
        return permission_denied(request)

    if request.method == 'POST':
        doc.delete()
        messages.success(request,
                         _("Document '{0}' deleted.").format(doc.title))
        return redirect('tuiuiudocs:index')

    return render(request, "tuiuiudocs/documents/confirm_delete.html", {
        'document': doc,
    })
コード例 #20
0
ファイル: views.py プロジェクト: waffle-iron/tuiuiu.io
def add(request):
    if request.method == 'POST':
        form = RedirectForm(request.POST, request.FILES)
        if form.is_valid():
            theredirect = form.save()

            messages.success(request, _("Redirect '{0}' added.").format(theredirect.title), buttons=[
                messages.button(reverse('tuiuiuredirects:edit', args=(theredirect.id,)), _('Edit'))
            ])
            return redirect('tuiuiuredirects:index')
        else:
            messages.error(request, _("The redirect could not be created due to errors."))
    else:
        form = RedirectForm()

    return render(request, "tuiuiuredirects/add.html", {
        'form': form,
    })
コード例 #21
0
def edit(request, app_label, model_name, id):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name('change', model)
    if not request.user.has_perm(permission):
        return permission_denied(request)

    instance = get_object_or_404(model, id=id)
    edit_handler_class = get_snippet_edit_handler(model)
    form_class = edit_handler_class.get_form_class(model)

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

        if form.is_valid():
            form.save()

            messages.success(
                request,
                _("{snippet_type} '{instance}' updated.").format(
                    snippet_type=capfirst(model._meta.verbose_name_plural),
                    instance=instance),
                buttons=[
                    messages.button(
                        reverse('tuiuiusnippets:edit',
                                args=(app_label, model_name, instance.id)),
                        _('Edit'))
                ])
            return redirect('tuiuiusnippets:list', app_label, model_name)
        else:
            messages.error(request,
                           _("The snippet could not be saved due to errors."))
            edit_handler = edit_handler_class(instance=instance, form=form)
    else:
        form = form_class(instance=instance)
        edit_handler = edit_handler_class(instance=instance, form=form)

    return render(
        request, 'tuiuiusnippets/snippets/edit.html', {
            'model_opts': model._meta,
            'instance': instance,
            'edit_handler': edit_handler,
            'form': form,
        })
コード例 #22
0
def add(request):
    if request.method == 'POST':
        # Get query
        query_form = search_forms.QueryForm(request.POST)
        if query_form.is_valid():
            query = Query.get(query_form['query_string'].value())

            # Save search picks
            searchpicks_formset = forms.SearchPromotionsFormSet(request.POST,
                                                                instance=query)
            if save_searchpicks(query, query, searchpicks_formset):
                messages.success(
                    request,
                    _("Editor's picks for '{0}' created.").format(query),
                    buttons=[
                        messages.button(
                            reverse('searchpromotions:edit',
                                    args=(query.id, )), _('Edit'))
                    ])
                return redirect('searchpromotions:index')
            else:
                if len(searchpicks_formset.non_form_errors()):
                    # formset level error (e.g. no forms submitted)
                    messages.error(
                        request,
                        " ".join(error for error in
                                 searchpicks_formset.non_form_errors()))
                else:
                    # specific errors will be displayed within form fields
                    messages.error(
                        request,
                        _("Recommendations have not been created due to errors"
                          ))
        else:
            searchpicks_formset = forms.SearchPromotionsFormSet()
    else:
        query_form = search_forms.QueryForm()
        searchpicks_formset = forms.SearchPromotionsFormSet()

    return render(request, 'searchpromotions/add.html', {
        'query_form': query_form,
        'searchpicks_formset': searchpicks_formset,
    })
コード例 #23
0
 def post(self, request, *args, **kwargs):
     try:
         msg = _("{model} '{instance}' deleted.").format(
             model=self.verbose_name, instance=self.instance)
         self.delete_instance()
         messages.success(request, msg)
         return redirect(self.index_url)
     except models.ProtectedError:
         linked_objects = []
         fields = self.model._meta.fields_map.values()
         fields = (obj for obj in fields
                   if not isinstance(obj.field, ManyToManyField))
         for rel in fields:
             if rel.on_delete == models.PROTECT:
                 qs = getattr(self.instance, rel.get_accessor_name())
                 for obj in qs.all():
                     linked_objects.append(obj)
         context = self.get_context_data(protected_error=True,
                                         linked_objects=linked_objects)
         return self.render_to_response(context)
コード例 #24
0
def delete(request, app_label, model_name, id):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name('delete', model)
    if not request.user.has_perm(permission):
        return permission_denied(request)

    instance = get_object_or_404(model, id=id)

    if request.method == 'POST':
        instance.delete()
        messages.success(
            request,
            _("{snippet_type} '{instance}' deleted.").format(
                snippet_type=capfirst(model._meta.verbose_name_plural),
                instance=instance))
        return redirect('tuiuiusnippets:list', app_label, model_name)

    return render(request, 'tuiuiusnippets/snippets/confirm_delete.html', {
        'model_opts': model._meta,
        'instance': instance,
    })
コード例 #25
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
def unpublish(request, page_id):
    page = get_object_or_404(Page, id=page_id).specific

    user_perms = UserPagePermissionsProxy(request.user)
    if not user_perms.for_page(page).can_unpublish():
        raise PermissionDenied

    next_url = get_valid_next_url_from_request(request)

    if request.method == 'POST':
        include_descendants = request.POST.get("include_descendants", False)

        page.unpublish()

        if include_descendants:
            live_descendant_pages = page.get_descendants().live().specific()
            for live_descendant_page in live_descendant_pages:
                if user_perms.for_page(live_descendant_page).can_unpublish():
                    live_descendant_page.unpublish()

        messages.success(request,
                         _("Page '{0}' unpublished.").format(
                             page.get_admin_display_title()),
                         buttons=[
                             messages.button(
                                 reverse('tuiuiuadmin_pages:edit',
                                         args=(page.id, )), _('Edit'))
                         ])

        if next_url:
            return redirect(next_url)
        return redirect('tuiuiuadmin_explore', page.get_parent().id)

    return render(
        request, 'tuiuiuadmin/pages/confirm_unpublish.html', {
            'page': page,
            'next': next_url,
            'live_descendant_count': page.get_descendants().live().count(),
        })
コード例 #26
0
def create(request):
    if request.method == 'POST':
        form = get_user_creation_form()(request.POST, request.FILES)
        if form.is_valid():
            user = form.save()
            messages.success(request,
                             _("User '{0}' created.").format(user),
                             buttons=[
                                 messages.button(
                                     reverse('tuiuiuusers_users:edit',
                                             args=(user.pk, )), _('Edit'))
                             ])
            return redirect('tuiuiuusers_users:index')
        else:
            messages.error(request,
                           _("The user could not be created due to errors."))
    else:
        form = get_user_creation_form()()

    return render(request, 'tuiuiuusers/users/create.html', {
        'form': form,
    })
コード例 #27
0
ファイル: groups.py プロジェクト: waffle-iron/tuiuiu.io
def edit(request, group_id):
    group = get_object_or_404(Group, id=group_id)
    if request.method == 'POST':
        form = GroupForm(request.POST, instance=group)
        permission_panels = [
            cls(request.POST, instance=group)
            for cls in get_permission_panel_classes()
        ]
        if form.is_valid() and all(panel.is_valid()
                                   for panel in permission_panels):
            form.save()

            for panel in permission_panels:
                panel.save()

            messages.success(request,
                             _("Group '{0}' updated.").format(group),
                             buttons=[
                                 messages.button(
                                     reverse('tuiuiuusers_groups:edit',
                                             args=(group.id, )), _('Edit'))
                             ])
            return redirect('tuiuiuusers_groups:index')
        else:
            messages.error(request,
                           _("The group could not be saved due to errors."))
    else:
        form = GroupForm(instance=group)
        permission_panels = [
            cls(instance=group) for cls in get_permission_panel_classes()
        ]

    return render(request, 'tuiuiuusers/groups/edit.html', {
        'group': group,
        'form': form,
        'permission_panels': permission_panels,
    })
コード例 #28
0
def add(request):
    ImageModel = get_image_model()
    ImageForm = get_image_form(ImageModel)

    if request.method == 'POST':
        image = ImageModel(uploaded_by_user=request.user)
        form = ImageForm(request.POST,
                         request.FILES,
                         instance=image,
                         user=request.user)
        if form.is_valid():
            # Set image file size
            image.file_size = image.file.size

            form.save()

            # Reindex the image to make sure all tags are indexed
            search_index.insert_or_update_object(image)

            messages.success(request,
                             _("Image '{0}' added.").format(image.title),
                             buttons=[
                                 messages.button(
                                     reverse('tuiuiuimages:edit',
                                             args=(image.id, )), _('Edit'))
                             ])
            return redirect('tuiuiuimages:index')
        else:
            messages.error(request,
                           _("The image could not be created due to errors."))
    else:
        form = ImageForm(user=request.user)

    return render(request, "tuiuiuimages/images/add.html", {
        'form': form,
    })
コード例 #29
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
def unlock(request, page_id):
    # Get the page
    page = get_object_or_404(Page, id=page_id).specific

    # Check permissions
    if not page.permissions_for_user(request.user).can_lock():
        raise PermissionDenied

    # Unlock the page
    if page.locked:
        page.locked = False
        page.save()

        messages.success(
            request,
            _("Page '{0}' is now unlocked.").format(
                page.get_admin_display_title()))

    # Redirect
    redirect_to = request.POST.get('next', None)
    if redirect_to and is_safe_url(url=redirect_to, host=request.get_host()):
        return redirect(redirect_to)
    else:
        return redirect('tuiuiuadmin_explore', page.get_parent().id)
コード例 #30
0
ファイル: pages.py プロジェクト: waffle-iron/tuiuiu.io
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()

    # Create the form
    form = CopyForm(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']

            if not page.permissions_for_user(request.user).can_copy_to(
                    parent_page, form.cleaned_data.get('copy_subpages')):
                raise PermissionDenied

            # 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()

            # Copy the page
            new_page = page.copy(
                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=(can_publish
                           and form.cleaned_data.get('publish_copies')),
                user=request.user,
            )

            # Give a success message back to the user
            if form.cleaned_data.get('copy_subpages'):
                messages.success(
                    request,
                    _("Page '{0}' and {1} subpages copied.").format(
                        page.get_admin_display_title(),
                        new_page.get_descendants().count()))
            else:
                messages.success(
                    request,
                    _("Page '{0}' copied.").format(
                        page.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('tuiuiuadmin_explore', parent_page.id)

    return render(request, 'tuiuiuadmin/pages/copy.html', {
        'page': page,
        'form': form,
        'next': next_url,
    })