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.POST: revision.publish() page_published.send(sender=revision.page.__class__, instance=revision.page.specific) messages.success(request, _("Page '{0}' published.").format(revision.page.title)) tasks.send_notification.delay(revision.id, 'approved', request.user.id) return redirect('wagtailadmin_home')
def publish(self): page = self.as_page_object() if page.go_live_at and page.go_live_at > timezone.now(): # if we have a go_live in the future don't make the page live page.live = False page.has_unpublished_changes = True # Instead set the approved_go_live_at of this revision self.approved_go_live_at = page.go_live_at self.save() # And clear the the approved_go_live_at of any other revisions page.revisions.exclude(id=self.id).update(approved_go_live_at=None) else: page.live = True # at this point, the page has unpublished changes iff there are newer revisions than this one page.has_unpublished_changes = not self.is_latest_revision() # If page goes live clear the approved_go_live_at of all revisions page.revisions.update(approved_go_live_at=None) page.expired = False # When a page is published it can't be expired page.save() self.submitted_for_moderation = False page.revisions.update(submitted_for_moderation=False) if page.live: page_published.send(sender=page.specific_class, instance=page.specific)
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(): is_publishing = bool(request.POST.get('action-publish')) and page_perms.can_publish() is_submitting = bool(request.POST.get('action-submit')) go_live_at = form.cleaned_data.get('go_live_at') future_go_live = go_live_at and go_live_at > timezone.now() approved_go_live_at = None if is_publishing: page.has_unpublished_changes = False page.expired = False if future_go_live: page.live = False # Set approved_go_live_at only if publishing approved_go_live_at = go_live_at else: page.live = True # We need save the page this way to workaround a bug # in django-modelcluster causing m2m fields to not # be committed to the database. See github issue #192 form.save(commit=False) page.save() # Clear approved_go_live_at for older revisions page.revisions.update( submitted_for_moderation=False, approved_go_live_at=None, ) else: # not publishing the page if page.live: # To avoid overwriting the live version, we only save the page # to the revisions table form.save(commit=False) Page.objects.filter(id=page.id).update(has_unpublished_changes=True) else: page.has_unpublished_changes = True form.save(commit=False) page.save() page.save_revision( user=request.user, submitted_for_moderation=is_submitting, approved_go_live_at=approved_go_live_at ) if is_publishing: page_published.send(sender=page.__class__, instance=page) 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_explore', page.get_parent().id) 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 })
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) # don't save yet, as we need treebeard to assign tree params is_publishing = bool(request.POST.get('action-publish')) and parent_page_perms.can_publish_subpage() is_submitting = bool(request.POST.get('action-submit')) go_live_at = form.cleaned_data.get('go_live_at') future_go_live = go_live_at and go_live_at > timezone.now() approved_go_live_at = None if is_publishing: page.has_unpublished_changes = False page.expired = False if future_go_live: page.live = False # Set approved_go_live_at only if is publishing # and the future_go_live is actually in future approved_go_live_at = go_live_at else: page.live = True else: page.live = False page.has_unpublished_changes = True parent_page.add_child(instance=page) # assign tree parameters - will cause page to be saved # Pass approved_go_live_at to save_revision page.save_revision( user=request.user, submitted_for_moderation=is_submitting, approved_go_live_at=approved_go_live_at ) if is_publishing: page_published.send(sender=page_class, instance=page) 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_explore', page.get_parent().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 })
def handle(self, *args, **options): dryrun = False if options['dryrun']: print("Will do a dry run.") dryrun = True # 1. get all expired pages with live = True expired_pages = Page.objects.filter( live=True, expire_at__lt=timezone.now() ) if dryrun: if expired_pages: print("Expired pages to be deactivated:") print("Expiry datetime\t\tSlug\t\tName") print("---------------\t\t----\t\t----") for ep in expired_pages: print("{0}\t{1}\t{2}".format( ep.expire_at.strftime("%Y-%m-%d %H:%M"), ep.slug, ep.title )) else: print("No expired pages to be deactivated found.") else: # need to get the list of expired pages before the update, # so that we can fire the page_unpublished signal on them afterwards expired_pages_list = list(expired_pages) expired_pages.update(expired=True, live=False) # Fire page_unpublished signal for all expired pages for page in expired_pages_list: page_unpublished.send(sender=page.specific_class, instance=page.specific) # 2. get all page revisions for moderation that have been expired expired_revs = [ r for r in PageRevision.objects.filter( submitted_for_moderation=True ) if revision_date_expired(r) ] if dryrun: print("---------------------------------") if expired_revs: print("Expired revisions to be dropped from moderation queue:") print("Expiry datetime\t\tSlug\t\tName") print("---------------\t\t----\t\t----") for er in expired_revs: rev_data = json.loads(er.content_json) print("{0}\t{1}\t{2}".format( dateparse.parse_datetime( rev_data.get('expire_at') ).strftime("%Y-%m-%d %H:%M"), rev_data.get('slug'), rev_data.get('title') )) else: print("No expired revision to be dropped from moderation.") else: for er in expired_revs: er.submitted_for_moderation = False er.save() # 3. get all revisions that need to be published revs_for_publishing = PageRevision.objects.filter( approved_go_live_at__lt=timezone.now() ) if dryrun: print("---------------------------------") if revs_for_publishing: print("Revisions to be published:") print("Go live datetime\t\tSlug\t\tName") print("---------------\t\t\t----\t\t----") for rp in revs_for_publishing: rev_data = json.loads(rp.content_json) print("{0}\t\t{1}\t{2}".format( rp.approved_go_live_at.strftime("%Y-%m-%d %H:%M"), rev_data.get('slug'), rev_data.get('title') )) else: print("No pages to go live.") else: for rp in revs_for_publishing: # just run publish for the revision -- since the approved go # live datetime is before now it will make the page live rp.publish() # Fire page_published signal page_published.send(sender=rp.page.specific_class, instance=rp.page.specific)
def handle(self, *args, **options): dryrun = False if options["dryrun"]: print("Will do a dry run.") dryrun = True # 1. get all expired pages with live = True expired_pages = Page.objects.filter(live=True, expire_at__lt=timezone.now()) if dryrun: if expired_pages: print("Expired pages to be deactivated:") print("Expiry datetime\t\tSlug\t\tName") print("---------------\t\t----\t\t----") for ep in expired_pages: print("{0}\t{1}\t{2}".format(ep.expire_at.strftime("%Y-%m-%d %H:%M"), ep.slug, ep.title)) else: print("No expired pages to be deactivated found.") else: # need to get the list of expired pages before the update, # so that we can fire the page_unpublished signal on them afterwards expired_pages_list = list(expired_pages) expired_pages.update(expired=True, live=False) # Fire page_unpublished signal for all expired pages for page in expired_pages_list: page_unpublished.send(sender=page.specific_class, instance=page.specific) # 2. get all page revisions for moderation that have been expired expired_revs = [ r for r in PageRevision.objects.filter(submitted_for_moderation=True) if revision_date_expired(r) ] if dryrun: print("---------------------------------") if expired_revs: print("Expired revisions to be dropped from moderation queue:") print("Expiry datetime\t\tSlug\t\tName") print("---------------\t\t----\t\t----") for er in expired_revs: rev_data = json.loads(er.content_json) print( "{0}\t{1}\t{2}".format( dateparse.parse_datetime(rev_data.get("expire_at")).strftime("%Y-%m-%d %H:%M"), rev_data.get("slug"), rev_data.get("title"), ) ) else: print("No expired revision to be dropped from moderation.") else: for er in expired_revs: er.submitted_for_moderation = False er.save() # 3. get all revisions that need to be published revs_for_publishing = PageRevision.objects.filter(approved_go_live_at__lt=timezone.now()) if dryrun: print("---------------------------------") if revs_for_publishing: print("Revisions to be published:") print("Go live datetime\t\tSlug\t\tName") print("---------------\t\t\t----\t\t----") for rp in revs_for_publishing: rev_data = json.loads(rp.content_json) print( "{0}\t\t{1}\t{2}".format( rp.approved_go_live_at.strftime("%Y-%m-%d %H:%M"), rev_data.get("slug"), rev_data.get("title"), ) ) else: print("No pages to go live.") else: for rp in revs_for_publishing: # just run publish for the revision -- since the approved go # live datetime is before now it will make the page live rp.publish() # Fire page_published signal page_published.send(sender=rp.page.specific_class, instance=rp.page.specific)