kopia lustrzana https://github.com/wagtail/wagtail
816 wiersze
30 KiB
Python
816 wiersze
30 KiB
Python
import warnings
|
|
|
|
from django.http import Http404, HttpResponse
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.core.exceptions import ValidationError, PermissionDenied
|
|
from django.contrib import messages
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.contrib.auth.decorators import permission_required
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
|
from django.utils import timezone
|
|
from django.utils.translation import ugettext as _
|
|
from django.utils.http import is_safe_url
|
|
from django.views.decorators.http import require_GET, require_POST
|
|
from django.views.decorators.vary import vary_on_headers
|
|
from django.db.models import Count
|
|
|
|
from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList
|
|
from wagtail.wagtailadmin.forms import SearchForm, CopyForm
|
|
from wagtail.wagtailadmin import tasks, signals
|
|
|
|
from wagtail.wagtailcore import hooks
|
|
from wagtail.wagtailcore.models import Page, PageRevision, get_navigation_menu_items
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def explorer_nav(request):
|
|
return render(request, 'wagtailadmin/shared/explorer_nav.html', {
|
|
'nodes': get_navigation_menu_items(),
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def index(request, parent_page_id=None):
|
|
if parent_page_id:
|
|
parent_page = get_object_or_404(Page, id=parent_page_id)
|
|
else:
|
|
parent_page = Page.get_first_root_node()
|
|
|
|
pages = parent_page.get_children().prefetch_related('content_type')
|
|
|
|
# Get page ordering
|
|
ordering = request.GET.get('ordering', '-latest_revision_created_at')
|
|
if ordering not in ['title', '-title', 'content_type', '-content_type', 'live', '-live', 'latest_revision_created_at', '-latest_revision_created_at', 'ord']:
|
|
ordering = '-latest_revision_created_at'
|
|
|
|
# Pagination
|
|
if ordering != 'ord':
|
|
ordering_no_minus = ordering
|
|
if ordering_no_minus.startswith('-'):
|
|
ordering_no_minus = ordering[1:]
|
|
pages = pages.order_by(ordering).annotate(null_position=Count(ordering_no_minus)).order_by('-null_position', ordering)
|
|
|
|
p = request.GET.get('p', 1)
|
|
paginator = Paginator(pages, 50)
|
|
try:
|
|
pages = paginator.page(p)
|
|
except PageNotAnInteger:
|
|
pages = paginator.page(1)
|
|
except EmptyPage:
|
|
pages = paginator.page(paginator.num_pages)
|
|
|
|
return render(request, 'wagtailadmin/pages/index.html', {
|
|
'parent_page': parent_page,
|
|
'ordering': ordering,
|
|
'pages': pages,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def add_subpage(request, parent_page_id):
|
|
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
|
if not parent_page.permissions_for_user(request.user).can_add_subpage():
|
|
raise PermissionDenied
|
|
|
|
page_types = sorted(parent_page.allowed_subpage_types(), key=lambda pagetype: pagetype.name.lower())
|
|
|
|
if len(page_types) == 1:
|
|
# Only one page type is available - redirect straight to the create form rather than
|
|
# making the user choose
|
|
content_type = page_types[0]
|
|
return redirect('wagtailadmin_pages_create', content_type.app_label, content_type.model, parent_page.id)
|
|
|
|
return render(request, 'wagtailadmin/pages/add_subpage.html', {
|
|
'parent_page': parent_page,
|
|
'page_types': page_types,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def content_type_use(request, content_type_app_name, content_type_model_name):
|
|
try:
|
|
content_type = ContentType.objects.get_by_natural_key(content_type_app_name, content_type_model_name)
|
|
except ContentType.DoesNotExist:
|
|
raise Http404
|
|
|
|
p = request.GET.get("p", 1)
|
|
|
|
page_class = content_type.model_class()
|
|
|
|
# page_class must be a Page type and not some other random model
|
|
if not issubclass(page_class, Page):
|
|
raise Http404
|
|
|
|
pages = page_class.objects.all()
|
|
|
|
paginator = Paginator(pages, 10)
|
|
|
|
try:
|
|
pages = paginator.page(p)
|
|
except PageNotAnInteger:
|
|
pages = paginator.page(1)
|
|
except EmptyPage:
|
|
pages = paginator.page(paginator.num_pages)
|
|
|
|
return render(request, 'wagtailadmin/pages/content_type_use.html', {
|
|
'pages': pages,
|
|
'app_name': content_type_app_name,
|
|
'content_type': content_type,
|
|
'page_class': page_class,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
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 content_type not in parent_page.allowed_subpage_types():
|
|
raise PermissionDenied
|
|
|
|
page = page_class(owner=request.user)
|
|
edit_handler_class = get_page_edit_handler(page_class)
|
|
form_class = edit_handler_class.get_form_class(page_class)
|
|
|
|
if request.POST:
|
|
form = form_class(request.POST, request.FILES, instance=page)
|
|
|
|
# Stick an extra validator into the form to make sure that the slug is not already in use
|
|
def clean_slug(slug):
|
|
# Make sure the slug isn't already in use
|
|
if parent_page.get_children().filter(slug=slug).count() > 0:
|
|
raise ValidationError(_("This slug is already in use"))
|
|
return slug
|
|
form.fields['slug'].clean = clean_slug
|
|
|
|
# Stick another validator into the form to check that the scheduled publishing settings are set correctly
|
|
def clean():
|
|
cleaned_data = form_class.clean(form)
|
|
|
|
# Go live must be before expire
|
|
go_live_at = cleaned_data.get('go_live_at')
|
|
expire_at = cleaned_data.get('expire_at')
|
|
|
|
if go_live_at and expire_at:
|
|
if go_live_at > expire_at:
|
|
msg = _('Go live date/time must be before expiry date/time')
|
|
form._errors['go_live_at'] = form.error_class([msg])
|
|
form._errors['expire_at'] = form.error_class([msg])
|
|
del cleaned_data['go_live_at']
|
|
del cleaned_data['expire_at']
|
|
|
|
# Expire must be in the future
|
|
expire_at = cleaned_data.get('expire_at')
|
|
|
|
if expire_at and expire_at < timezone.now():
|
|
form._errors['expire_at'] = form.error_class([_('Expiry date/time must be in the future')])
|
|
del cleaned_data['expire_at']
|
|
|
|
return cleaned_data
|
|
form.clean = clean
|
|
|
|
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'))
|
|
|
|
# Set live to False and has_unpublished_changes to True if we are not publishing
|
|
if not is_publishing:
|
|
page.live = False
|
|
page.has_unpublished_changes = True
|
|
|
|
# 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:
|
|
messages.success(request, _("Page '{0}' published.").format(page.title))
|
|
elif is_submitting:
|
|
messages.success(request, _("Page '{0}' submitted for moderation.").format(page.title))
|
|
tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id)
|
|
else:
|
|
messages.success(request, _("Page '{0}' created.").format(page.title))
|
|
|
|
for fn in hooks.get_hooks('after_create_page'):
|
|
result = fn(request, page)
|
|
if hasattr(result, 'status_code'):
|
|
return result
|
|
|
|
return redirect('wagtailadmin_pages_edit', page.id)
|
|
else:
|
|
messages.error(request, _("The page could not be created due to validation errors"))
|
|
edit_handler = edit_handler_class(instance=page, form=form)
|
|
else:
|
|
signals.init_new_page.send(sender=create, page=page, parent=parent_page)
|
|
form = form_class(instance=page)
|
|
edit_handler = edit_handler_class(instance=page, 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,
|
|
'preview_modes': page.preview_modes,
|
|
'form': form, # Used in unit tests
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def edit(request, page_id):
|
|
latest_revision = get_object_or_404(Page, id=page_id).get_latest_revision()
|
|
page = get_object_or_404(Page, id=page_id).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
|
|
|
|
edit_handler_class = get_page_edit_handler(page.__class__)
|
|
form_class = edit_handler_class.get_form_class(page.__class__)
|
|
|
|
errors_debug = None
|
|
|
|
if request.POST:
|
|
form = form_class(request.POST, request.FILES, instance=page)
|
|
|
|
# Stick an extra validator into the form to make sure that the slug is not already in use
|
|
def clean_slug(slug):
|
|
# Make sure the slug isn't already in use
|
|
if parent.get_children().filter(slug=slug).exclude(id=page_id).count() > 0:
|
|
raise ValidationError(_("This slug is already in use"))
|
|
return slug
|
|
form.fields['slug'].clean = clean_slug
|
|
|
|
# Stick another validator into the form to check that the scheduled publishing settings are set correctly
|
|
def clean():
|
|
cleaned_data = form_class.clean(form)
|
|
|
|
# Go live must be before expire
|
|
go_live_at = cleaned_data.get('go_live_at')
|
|
expire_at = cleaned_data.get('expire_at')
|
|
|
|
if go_live_at and expire_at:
|
|
if go_live_at > expire_at:
|
|
msg = _('Go live date/time must be before expiry date/time')
|
|
form._errors['go_live_at'] = form.error_class([msg])
|
|
form._errors['expire_at'] = form.error_class([msg])
|
|
del cleaned_data['go_live_at']
|
|
del cleaned_data['expire_at']
|
|
|
|
# Expire must be in the future
|
|
expire_at = cleaned_data.get('expire_at')
|
|
|
|
if expire_at and expire_at < timezone.now():
|
|
form._errors['expire_at'] = form.error_class([_('Expiry date/time must be in the future')])
|
|
del cleaned_data['expire_at']
|
|
|
|
return cleaned_data
|
|
form.clean = clean
|
|
|
|
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'))
|
|
|
|
# Save revision
|
|
revision = page.save_revision(
|
|
user=request.user,
|
|
submitted_for_moderation=is_submitting,
|
|
)
|
|
|
|
# Publish
|
|
if is_publishing:
|
|
revision.publish()
|
|
else:
|
|
# Set has_unpublished_changes flag
|
|
if page.live:
|
|
# To avoid overwriting the live version, we only save the page
|
|
# to the revisions table
|
|
Page.objects.filter(id=page.id).update(has_unpublished_changes=True)
|
|
else:
|
|
page.has_unpublished_changes = True
|
|
page.save()
|
|
|
|
# Notifications
|
|
if is_publishing:
|
|
messages.success(request, _("Page '{0}' published.").format(page.title))
|
|
elif is_submitting:
|
|
messages.success(request, _("Page '{0}' submitted for moderation.").format(page.title))
|
|
tasks.send_notification.delay(page.get_latest_revision().id, 'submitted', request.user.id)
|
|
else:
|
|
messages.success(request, _("Page '{0}' updated.").format(page.title))
|
|
|
|
for fn in hooks.get_hooks('after_edit_page'):
|
|
result = fn(request, page)
|
|
if hasattr(result, 'status_code'):
|
|
return result
|
|
|
|
return redirect('wagtailadmin_pages_edit', page.id)
|
|
else:
|
|
if page.locked:
|
|
messages.error(request, _("The page could not be saved as it is locked"))
|
|
else:
|
|
messages.error(request, _("The page could not be saved due to validation errors"))
|
|
|
|
edit_handler = edit_handler_class(instance=page, form=form)
|
|
errors_debug = (
|
|
repr(edit_handler.form.errors)
|
|
+ repr([(name, formset.errors) for (name, formset) in edit_handler.form.formsets.items() if formset.errors])
|
|
)
|
|
else:
|
|
form = form_class(instance=page)
|
|
edit_handler = edit_handler_class(instance=page, form=form)
|
|
|
|
# Check for revisions still undergoing moderation and warn
|
|
if latest_revision and latest_revision.submitted_for_moderation:
|
|
messages.warning(request, _("This page is currently awaiting moderation"))
|
|
|
|
return render(request, 'wagtailadmin/pages/edit.html', {
|
|
'page': page,
|
|
'edit_handler': edit_handler,
|
|
'errors_debug': errors_debug,
|
|
'preview_modes': page.preview_modes,
|
|
'form': form, # Used in unit tests
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def delete(request, page_id):
|
|
page = get_object_or_404(Page, id=page_id).specific
|
|
if not page.permissions_for_user(request.user).can_delete():
|
|
raise PermissionDenied
|
|
|
|
if request.POST:
|
|
parent_id = page.get_parent().id
|
|
page.delete()
|
|
|
|
messages.success(request, _("Page '{0}' deleted.").format(page.title))
|
|
|
|
for fn in hooks.get_hooks('after_delete_page'):
|
|
result = fn(request, page)
|
|
if hasattr(result, 'status_code'):
|
|
return result
|
|
|
|
return redirect('wagtailadmin_explore', parent_id)
|
|
|
|
return render(request, 'wagtailadmin/pages/confirm_delete.html', {
|
|
'page': page,
|
|
'descendant_count': page.get_descendant_count()
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def view_draft(request, page_id):
|
|
page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
|
|
return page.serve_preview(page.dummy_request(), page.default_preview_mode)
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def preview_on_edit(request, page_id):
|
|
# Receive the form submission that would typically be posted to the 'edit' view. If submission is valid,
|
|
# return the rendered page; if not, re-render the edit form
|
|
page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
|
|
edit_handler_class = get_page_edit_handler(page.__class__)
|
|
form_class = edit_handler_class.get_form_class(page.__class__)
|
|
|
|
form = form_class(request.POST, request.FILES, instance=page)
|
|
|
|
if form.is_valid():
|
|
form.save(commit=False)
|
|
|
|
preview_mode = request.GET.get('mode', page.default_preview_mode)
|
|
response = page.serve_preview(page.dummy_request(), preview_mode)
|
|
response['X-Wagtail-Preview'] = 'ok'
|
|
return response
|
|
|
|
else:
|
|
edit_handler = edit_handler_class(instance=page, form=form)
|
|
|
|
response = render(request, 'wagtailadmin/pages/edit.html', {
|
|
'page': page,
|
|
'edit_handler': edit_handler,
|
|
'preview_modes': page.preview_modes,
|
|
})
|
|
response['X-Wagtail-Preview'] = 'error'
|
|
return response
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def preview_on_create(request, content_type_app_name, content_type_model_name, parent_page_id):
|
|
# Receive the form submission that would typically be posted to the 'create' view. If submission is valid,
|
|
# return the rendered page; if not, re-render the edit form
|
|
try:
|
|
content_type = ContentType.objects.get_by_natural_key(content_type_app_name, content_type_model_name)
|
|
except ContentType.DoesNotExist:
|
|
raise Http404
|
|
|
|
page_class = content_type.model_class()
|
|
page = page_class()
|
|
edit_handler_class = get_page_edit_handler(page_class)
|
|
form_class = edit_handler_class.get_form_class(page_class)
|
|
|
|
form = form_class(request.POST, request.FILES, instance=page)
|
|
|
|
if form.is_valid():
|
|
form.save(commit=False)
|
|
|
|
# ensure that our unsaved page instance has a suitable url set
|
|
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
|
page.set_url_path(parent_page)
|
|
|
|
# Set treebeard attributes
|
|
page.depth = parent_page.depth + 1
|
|
page.path = Page._get_children_path_interval(parent_page.path)[1]
|
|
|
|
preview_mode = request.GET.get('mode', page.default_preview_mode)
|
|
response = page.serve_preview(page.dummy_request(), preview_mode)
|
|
response['X-Wagtail-Preview'] = 'ok'
|
|
return response
|
|
|
|
else:
|
|
edit_handler = edit_handler_class(instance=page, form=form)
|
|
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
|
|
|
response = render(request, 'wagtailadmin/pages/create.html', {
|
|
'content_type': content_type,
|
|
'page_class': page_class,
|
|
'parent_page': parent_page,
|
|
'edit_handler': edit_handler,
|
|
'preview_modes': page.preview_modes,
|
|
})
|
|
response['X-Wagtail-Preview'] = 'error'
|
|
return response
|
|
|
|
|
|
def preview(request):
|
|
"""
|
|
The HTML of a previewed page is written to the destination browser window using document.write.
|
|
This overwrites any previous content in the window, while keeping its URL intact. This in turn
|
|
means that any content we insert that happens to trigger an HTTP request, such as an image or
|
|
stylesheet tag, will report that original URL as its referrer.
|
|
|
|
In Webkit browsers, a new window opened with window.open('', 'window_name') will have a location
|
|
of 'about:blank', causing it to omit the Referer header on those HTTP requests. This means that
|
|
any third-party font services that use the Referer header for access control will refuse to
|
|
serve us.
|
|
|
|
So, instead, we need to open the window on some arbitrary URL on our domain. (Provided that's
|
|
also the same domain as our editor JS code, the browser security model will happily allow us to
|
|
document.write over the page in question.)
|
|
|
|
This, my friends, is that arbitrary URL.
|
|
|
|
Since we're going to this trouble, we'll also take the opportunity to display a spinner on the
|
|
placeholder page, providing some much-needed visual feedback.
|
|
"""
|
|
return render(request, 'wagtailadmin/pages/preview.html')
|
|
|
|
def preview_loading(request):
|
|
"""
|
|
This page is blank, but must be real HTML so its DOM can be written to once the preview of the page has rendered
|
|
"""
|
|
return HttpResponse("<html><head><title></title></head><body></body></html>")
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def unpublish(request, page_id):
|
|
page = get_object_or_404(Page, id=page_id).specific
|
|
if not page.permissions_for_user(request.user).can_unpublish():
|
|
raise PermissionDenied
|
|
|
|
if request.method == 'POST':
|
|
page.unpublish()
|
|
|
|
messages.success(request, _("Page '{0}' unpublished.").format(page.title))
|
|
|
|
return redirect('wagtailadmin_explore', page.get_parent().id)
|
|
|
|
return render(request, 'wagtailadmin/pages/confirm_unpublish.html', {
|
|
'page': page,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def move_choose_destination(request, page_to_move_id, viewed_page_id=None):
|
|
page_to_move = get_object_or_404(Page, id=page_to_move_id)
|
|
page_perms = page_to_move.permissions_for_user(request.user)
|
|
if not page_perms.can_move():
|
|
raise PermissionDenied
|
|
|
|
if viewed_page_id:
|
|
viewed_page = get_object_or_404(Page, id=viewed_page_id)
|
|
else:
|
|
viewed_page = Page.get_first_root_node()
|
|
|
|
viewed_page.can_choose = page_perms.can_move_to(viewed_page)
|
|
|
|
child_pages = []
|
|
for target in viewed_page.get_children():
|
|
# can't move the page into itself or its descendants
|
|
target.can_choose = page_perms.can_move_to(target)
|
|
|
|
target.can_descend = not(target == page_to_move or target.is_child_of(page_to_move)) and target.get_children_count()
|
|
|
|
child_pages.append(target)
|
|
|
|
return render(request, 'wagtailadmin/pages/move_choose_destination.html', {
|
|
'page_to_move': page_to_move,
|
|
'viewed_page': viewed_page,
|
|
'child_pages': child_pages,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
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.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.title))
|
|
return redirect('wagtailadmin_explore', destination.id)
|
|
|
|
return render(request, 'wagtailadmin/pages/confirm_move.html', {
|
|
'page_to_move': page_to_move,
|
|
'destination': destination,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def set_page_position(request, page_to_move_id):
|
|
page_to_move = get_object_or_404(Page, id=page_to_move_id)
|
|
parent_page = page_to_move.get_parent()
|
|
|
|
if not parent_page.permissions_for_user(request.user).can_reorder_children():
|
|
raise PermissionDenied
|
|
|
|
if request.POST:
|
|
# Get position parameter
|
|
position = request.GET.get('position', None)
|
|
|
|
# Find page thats already in this position
|
|
position_page = None
|
|
if position is not None:
|
|
try:
|
|
position_page = parent_page.get_children()[int(position)]
|
|
except IndexError:
|
|
pass # No page in this position
|
|
|
|
# Move page
|
|
|
|
# any invalid moves *should* be caught by the permission check above,
|
|
# so don't bother to catch InvalidMoveToDescendant
|
|
|
|
if position_page:
|
|
# If the page has been moved to the right, insert it to the
|
|
# right. If left, then left.
|
|
old_position = list(parent_page.get_children()).index(page_to_move)
|
|
if int(position) < old_position:
|
|
page_to_move.move(position_page, pos='left')
|
|
elif int(position) > old_position:
|
|
page_to_move.move(position_page, pos='right')
|
|
else:
|
|
# Move page to end
|
|
page_to_move.move(parent_page, pos='last-child')
|
|
|
|
return HttpResponse('')
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def copy(request, page_id):
|
|
page = Page.objects.get(id=page_id)
|
|
parent_page = page.get_parent()
|
|
|
|
# Make sure this user has permission to add subpages on the parent
|
|
if not parent_page.permissions_for_user(request.user).can_add_subpage():
|
|
raise PermissionDenied
|
|
|
|
# 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, page=page, can_publish=can_publish)
|
|
|
|
# Check if user is submitting
|
|
if request.method == 'POST' and form.is_valid():
|
|
# Copy the page
|
|
new_page = page.copy(
|
|
recursive=form.cleaned_data.get('copy_subpages'),
|
|
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')),
|
|
)
|
|
|
|
# Assign user of this request as the owner of all the new pages
|
|
new_page.get_descendants(inclusive=True).update(owner=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.title, new_page.get_descendants().count()))
|
|
else:
|
|
messages.success(request, _("Page '{0}' copied.").format(page.title))
|
|
|
|
# Redirect to explore of parent page
|
|
return redirect('wagtailadmin_explore', parent_page.id)
|
|
|
|
return render(request, 'wagtailadmin/pages/copy.html', {
|
|
'page': page,
|
|
'form': form,
|
|
})
|
|
|
|
|
|
PAGE_EDIT_HANDLERS = {}
|
|
|
|
|
|
def get_page_edit_handler(page_class):
|
|
if page_class not in PAGE_EDIT_HANDLERS:
|
|
PAGE_EDIT_HANDLERS[page_class] = TabbedInterface([
|
|
ObjectList(page_class.content_panels, heading='Content'),
|
|
ObjectList(page_class.promote_panels, heading='Promote'),
|
|
ObjectList(page_class.settings_panels, heading='Settings', classname="settings")
|
|
])
|
|
|
|
return PAGE_EDIT_HANDLERS[page_class]
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
@vary_on_headers('X-Requested-With')
|
|
def search(request):
|
|
pages = []
|
|
q = None
|
|
is_searching = False
|
|
if 'q' in request.GET:
|
|
form = SearchForm(request.GET)
|
|
if form.is_valid():
|
|
q = form.cleaned_data['q']
|
|
|
|
# page number
|
|
p = request.GET.get("p", 1)
|
|
is_searching = True
|
|
pages = Page.search(q, show_unpublished=True, search_title_only=True, prefetch_related=['content_type'])
|
|
|
|
# Pagination
|
|
paginator = Paginator(pages, 20)
|
|
try:
|
|
pages = paginator.page(p)
|
|
except PageNotAnInteger:
|
|
pages = paginator.page(1)
|
|
except EmptyPage:
|
|
pages = paginator.page(paginator.num_pages)
|
|
else:
|
|
form = SearchForm()
|
|
|
|
if request.is_ajax():
|
|
return render(request, "wagtailadmin/pages/search_results.html", {
|
|
'pages': pages,
|
|
'is_searching': is_searching,
|
|
'query_string': q,
|
|
})
|
|
else:
|
|
return render(request, "wagtailadmin/pages/search.html", {
|
|
'search_form': form,
|
|
'pages': pages,
|
|
'is_searching': is_searching,
|
|
'query_string': q,
|
|
})
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
def approve_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.title))
|
|
return redirect('wagtailadmin_home')
|
|
|
|
if request.method == 'POST':
|
|
revision.approve_moderation()
|
|
messages.success(request, _("Page '{0}' published.").format(revision.page.title))
|
|
tasks.send_notification.delay(revision.id, 'approved', request.user.id)
|
|
|
|
return redirect('wagtailadmin_home')
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
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.title))
|
|
return redirect('wagtailadmin_home')
|
|
|
|
if request.method == 'POST':
|
|
revision.reject_moderation()
|
|
messages.success(request, _("Page '{0}' rejected for publication.").format(revision.page.title))
|
|
tasks.send_notification.delay(revision.id, 'rejected', request.user.id)
|
|
|
|
return redirect('wagtailadmin_home')
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
@require_GET
|
|
def preview_for_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.title))
|
|
return redirect('wagtailadmin_home')
|
|
|
|
page = revision.as_page_object()
|
|
|
|
request.revision_id = revision_id
|
|
|
|
# pass in the real user request rather than page.dummy_request(), so that request.user
|
|
# and request.revision_id will be picked up by the wagtail user bar
|
|
return page.serve_preview(request, page.default_preview_mode)
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
@require_POST
|
|
def lock(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
|
|
|
|
# Lock the page
|
|
if not page.locked:
|
|
page.locked = True
|
|
page.save()
|
|
|
|
messages.success(request, _("Page '{0}' is now locked.").format(page.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('wagtailadmin_explore', page.get_parent().id)
|
|
|
|
|
|
@permission_required('wagtailadmin.access_admin')
|
|
@require_POST
|
|
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.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('wagtailadmin_explore', page.get_parent().id)
|