示例#1
0
文件: users.py 项目: tomusher/wagtail
def create(request):
    for fn in hooks.get_hooks('before_create_user'):
        result = fn(request)
        if hasattr(result, 'status_code'):
            return result
    if request.method == 'POST':
        form = get_user_creation_form()(request.POST, request.FILES)
        if form.is_valid():
            with transaction.atomic():
                user = form.save()
                log(user, 'wagtail.create')
            messages.success(request,
                             _("User '{0}' created.").format(user),
                             buttons=[
                                 messages.button(
                                     reverse('wagtailusers_users:edit',
                                             args=(user.pk, )), _('Edit'))
                             ])
            for fn in hooks.get_hooks('after_create_user'):
                result = fn(request, user)
                if hasattr(result, 'status_code'):
                    return result
            return redirect('wagtailusers_users:index')
        else:
            messages.error(request,
                           _("The user could not be created due to errors."))
    else:
        form = get_user_creation_form()()

    return TemplateResponse(request, 'wagtailusers/users/create.html', {
        'form': form,
    })
示例#2
0
文件: users.py 项目: jams2/wagtail
def delete(request, user_id):
    user = get_object_or_404(User, pk=user_id)

    if not user_can_delete_user(request.user, user):
        raise PermissionDenied

    for fn in hooks.get_hooks("before_delete_user"):
        result = fn(request, user)
        if hasattr(result, "status_code"):
            return result
    if request.method == "POST":
        with transaction.atomic():
            log(user, "wagtail.delete")
            user.delete()
        messages.success(request, _("User '{0}' deleted.").format(user))
        for fn in hooks.get_hooks("after_delete_user"):
            result = fn(request, user)
            if hasattr(result, "status_code"):
                return result
        return redirect("wagtailusers_users:index")

    return TemplateResponse(
        request,
        "wagtailusers/users/confirm_delete.html",
        {
            "user": user,
        },
    )
示例#3
0
def add(request):
    if request.method == "POST":
        form = RedirectForm(request.POST, request.FILES)
        if form.is_valid():
            with transaction.atomic():
                theredirect = form.save()
                log(instance=theredirect, action="wagtail.edit")

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

    return TemplateResponse(
        request,
        "wagtailredirects/add.html",
        {
            "form": form,
        },
    )
示例#4
0
 def post(self, request, *args, **kwargs):
     try:
         msg = _("%(model_name)s '%(instance)s' deleted.") % {
             "model_name": self.verbose_name,
             "instance": self.instance,
         }
         with transaction.atomic():
             log(instance=self.instance, action="wagtail.delete")
             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:
                 if isinstance(rel, OneToOneRel):
                     try:
                         obj = getattr(self.instance,
                                       rel.get_accessor_name())
                     except ObjectDoesNotExist:
                         pass
                     else:
                         linked_objects.append(obj)
                 else:
                     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)
示例#5
0
    def _unpublish_page(self, page, set_expired, commit, user, log_action):
        """
        Unpublish the page by setting ``live`` to ``False``. Does nothing if ``live`` is already ``False``
        :param log_action: flag for logging the action. Pass False to skip logging. Can be passed an action string.
            Defaults to 'wagtail.unpublish'
        """
        if page.live:
            page.live = False
            page.has_unpublished_changes = True
            page.live_revision = None

            if set_expired:
                page.expired = True

            if commit:
                # using clean=False to bypass validation
                page.save(clean=False)

            page_unpublished.send(sender=page.specific_class, instance=page.specific)

            if log_action:
                log(
                    instance=page,
                    action=log_action if isinstance(log_action, str) else "wagtail.unpublish",
                    user=user,
                )

            logger.info('Page unpublished: "%s" id=%d', page.title, page.id)

            page.revisions.update(approved_go_live_at=None)

            # Unpublish aliases
            for alias in page.aliases.all():
                alias.unpublish()
示例#6
0
 def log_deletion(self, page):
     log(
         instance=page,
         action="wagtail.delete",
         user=self.user,
         deleted=True,
     )
示例#7
0
    def _convert_alias(self, page, log_action, user):
        page.alias_of_id = None
        page.save(update_fields=["alias_of_id"], clean=False)

        # Create an initial revision
        revision = page.save_revision(user=user, changed=False, clean=False)

        if page.live:
            page.live_revision = revision
            page.save(update_fields=["live_revision"], clean=False)

        # Log
        if log_action:
            log(
                instance=page,
                action=log_action,
                revision=revision,
                user=user,
                data={
                    "page": {
                        "id": page.id,
                        "title": page.get_admin_display_title()
                    },
                },
            )

        return page
示例#8
0
文件: models.py 项目: tbrlpld/wagtail
 def delete(self, request, *args, **kwargs):
     self.object = self.get_object()
     success_url = self.get_success_url()
     with transaction.atomic():
         log(instance=self.object, action='wagtail.delete')
         self.object.delete()
     messages.success(request, self.get_success_message())
     return HttpResponseRedirect(success_url)
示例#9
0
文件: views.py 项目: jams2/wagtail
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 = get_setting_edit_handler(model)
    edit_handler = edit_handler.bind_to(instance=instance, request=request)
    form_class = edit_handler.get_form_class()

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

        if form.is_valid():
            with transaction.atomic():
                form.save()
                log(instance, "wagtail.edit")

            messages.success(
                request,
                _("%(setting_type)s updated.") % {
                    "setting_type": capfirst(setting_type_name),
                    "instance": instance
                },
            )
            return redirect("wagtailsettings:edit", app_name, model_name,
                            site.pk)
        else:
            messages.validation_error(
                request, _("The setting could not be saved due to errors."),
                form)
    else:
        form = form_class(instance=instance)

    edit_handler = edit_handler.bind_to(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 TemplateResponse(
        request,
        "wagtailsettings/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": isinstance(edit_handler, TabbedInterface),
        },
    )
示例#10
0
文件: users.py 项目: jams2/wagtail
def edit(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    can_delete = user_can_delete_user(request.user, user)
    editing_self = request.user == user

    for fn in hooks.get_hooks("before_edit_user"):
        result = fn(request, user)
        if hasattr(result, "status_code"):
            return result
    if request.method == "POST":
        form = get_user_edit_form()(request.POST,
                                    request.FILES,
                                    instance=user,
                                    editing_self=editing_self)
        if form.is_valid():
            with transaction.atomic():
                user = form.save()
                log(user, "wagtail.edit")

            if user == request.user and "password1" in form.changed_data:
                # User is changing their own password; need to update their session hash
                update_session_auth_hash(request, user)

            messages.success(
                request,
                _("User '{0}' updated.").format(user),
                buttons=[
                    messages.button(
                        reverse("wagtailusers_users:edit", args=(user.pk, )),
                        _("Edit"))
                ],
            )
            for fn in hooks.get_hooks("after_edit_user"):
                result = fn(request, user)
                if hasattr(result, "status_code"):
                    return result
            return redirect("wagtailusers_users:index")
        else:
            messages.error(request,
                           _("The user could not be saved due to errors."))
    else:
        form = get_user_edit_form()(instance=user, editing_self=editing_self)

    return TemplateResponse(
        request,
        "wagtailusers/users/edit.html",
        {
            "user": user,
            "form": form,
            "can_delete": can_delete,
        },
    )
示例#11
0
文件: views.py 项目: tomusher/wagtail
def delete(request, query_id):
    query = get_object_or_404(Query, id=query_id)

    if request.method == 'POST':
        editors_picks = query.editors_picks.all()
        with transaction.atomic():
            for search_pick in editors_picks:
                log(search_pick, 'wagtail.delete')
            editors_picks.delete()
        messages.success(request, _("Editor's picks deleted."))
        return redirect('wagtailsearchpromotions:index')

    return TemplateResponse(request,
                            'wagtailsearchpromotions/confirm_delete.html', {
                                'query': query,
                            })
示例#12
0
 def form_valid(self, form):
     self.form = form
     with transaction.atomic():
         self.object = self.save_instance()
         log(instance=self.object, action='wagtail.edit')
     success_message = self.get_success_message()
     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())
示例#13
0
文件: views.py 项目: tomusher/wagtail
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):
                for search_pick in searchpicks_formset.new_objects:
                    log(search_pick, 'wagtail.create')
                messages.success(
                    request,
                    _("Editor's picks for '{0}' created.").format(query),
                    buttons=[
                        messages.button(
                            reverse('wagtailsearchpromotions:edit',
                                    args=(query.id, )), _('Edit'))
                    ])
                return redirect('wagtailsearchpromotions: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 TemplateResponse(
        request, 'wagtailsearchpromotions/add.html', {
            'query_form': query_form,
            'searchpicks_formset': searchpicks_formset,
            'form_media': query_form.media + searchpicks_formset.media,
        })
示例#14
0
 def log_scheduling_action(self):
     log(
         instance=self.page,
         action="wagtail.publish.schedule",
         user=self.user,
         data={
             "revision": {
                 "id": self.revision.id,
                 "created":
                 self.revision.created_at.strftime("%d %b %Y %H:%M"),
                 "go_live_at":
                 self.page.go_live_at.strftime("%d %b %Y %H:%M"),
                 "has_live_version": self.page.live,
             }
         },
         revision=self.revision,
         content_changed=self.changed,
     )
示例#15
0
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):
        raise PermissionDenied

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

    return TemplateResponse(
        request,
        "wagtailredirects/edit.html",
        {
            "redirect":
            theredirect,
            "form":
            form,
            "user_can_delete":
            permission_policy.user_has_permission(request.user, "delete"),
        },
    )
示例#16
0
文件: views.py 项目: tomusher/wagtail
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):
        raise PermissionDenied

    if request.method == 'POST':
        with transaction.atomic():
            log(instance=theredirect, action='wagtail.delete')
            theredirect.delete()
        messages.success(
            request,
            _("Redirect '{0}' deleted.").format(theredirect.title))
        return redirect('wagtailredirects:index')

    return TemplateResponse(request, "wagtailredirects/confirm_delete.html", {
        'redirect': theredirect,
    })
示例#17
0
文件: users.py 项目: jams2/wagtail
def create(request):
    for fn in hooks.get_hooks("before_create_user"):
        result = fn(request)
        if hasattr(result, "status_code"):
            return result
    if request.method == "POST":
        form = get_user_creation_form()(request.POST, request.FILES)
        if form.is_valid():
            with transaction.atomic():
                user = form.save()
                log(user, "wagtail.create")
            messages.success(
                request,
                _("User '{0}' created.").format(user),
                buttons=[
                    messages.button(
                        reverse("wagtailusers_users:edit", args=(user.pk, )),
                        _("Edit"))
                ],
            )
            for fn in hooks.get_hooks("after_create_user"):
                result = fn(request, user)
                if hasattr(result, "status_code"):
                    return result
            return redirect("wagtailusers_users:index")
        else:
            messages.error(request,
                           _("The user could not be created due to errors."))
    else:
        form = get_user_creation_form()()

    return TemplateResponse(
        request,
        "wagtailusers/users/create.html",
        {
            "form": form,
        },
    )
示例#18
0
def create_redirects_from_dataset(dataset, config):
    errors = []
    successes = 0
    total = 0

    for row in dataset:
        total += 1

        from_link = row[config["from_index"]]
        to_link = row[config["to_index"]]

        data = {
            "old_path": from_link,
            "redirect_link": to_link,
            "is_permanent": config["permanent"],
        }

        if config["site"]:
            data["site"] = config["site"].pk

        form = RedirectForm(data)
        if not form.is_valid():
            error = to_readable_errors(form.errors.as_text())
            errors.append([from_link, to_link, error])
            continue

        with transaction.atomic():
            redirect = form.save()
            log(instance=redirect, action="wagtail.create")
        successes += 1

    return {
        "errors": errors,
        "errors_count": len(errors),
        "successes": successes,
        "total": total,
    }
示例#19
0
文件: views.py 项目: tomusher/wagtail
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):
        raise PermissionDenied

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

    return TemplateResponse(
        request, "wagtailredirects/edit.html", {
            'redirect':
            theredirect,
            'form':
            form,
            'user_can_delete':
            permission_policy.user_has_permission(request.user, 'delete'),
        })
示例#20
0
文件: views.py 项目: tomusher/wagtail
def save_searchpicks(query, new_query, searchpicks_formset):
    # Save
    if searchpicks_formset.is_valid():
        # Set sort_order
        for i, form in enumerate(searchpicks_formset.ordered_forms):
            form.instance.sort_order = i

            # Make sure the form is marked as changed so it gets saved with the new order
            form.has_changed = lambda: True

        # log deleted items before saving, otherwise we lose their IDs
        items_for_deletion = [
            form.instance for form in searchpicks_formset.deleted_forms
            if form.instance.pk
        ]
        with transaction.atomic():
            for search_pick in items_for_deletion:
                log(search_pick, 'wagtail.delete')

            searchpicks_formset.save()

            for search_pick in searchpicks_formset.new_objects:
                log(search_pick, 'wagtail.create')

            # If query was changed, move all search picks to the new query
            if query != new_query:
                searchpicks_formset.get_queryset().update(query=new_query)
                # log all items in the formset as having changed
                for search_pick, changed_fields in searchpicks_formset.changed_objects:
                    log(search_pick, 'wagtail.edit')
            else:
                # only log objects with actual changes
                for search_pick, changed_fields in searchpicks_formset.changed_objects:
                    if changed_fields:
                        log(search_pick, 'wagtail.edit')

        return True
    else:
        return False
示例#21
0
文件: snippets.py 项目: jams2/wagtail
def create(request, app_label, model_name):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name("add", model)
    if not request.user.has_perm(permission):
        raise PermissionDenied

    for fn in hooks.get_hooks("before_create_snippet"):
        result = fn(request, model)
        if hasattr(result, "status_code"):
            return result

    instance = model()

    # Set locale of the new instance
    if issubclass(model, TranslatableMixin):
        selected_locale = request.GET.get("locale")
        if selected_locale:
            instance.locale = get_object_or_404(Locale,
                                                language_code=selected_locale)
        else:
            instance.locale = Locale.get_default()

    # Make edit handler
    edit_handler = get_snippet_edit_handler(model)
    edit_handler = edit_handler.bind_to(request=request)
    form_class = edit_handler.get_form_class()

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

        if form.is_valid():
            with transaction.atomic():
                form.save()
                log(instance=instance, action="wagtail.create")

            messages.success(
                request,
                _("%(snippet_type)s '%(instance)s' created.") % {
                    "snippet_type": capfirst(model._meta.verbose_name),
                    "instance": instance,
                },
                buttons=[
                    messages.button(
                        reverse(
                            "wagtailsnippets:edit",
                            args=(app_label, model_name, quote(instance.pk)),
                        ),
                        _("Edit"),
                    )
                ],
            )

            for fn in hooks.get_hooks("after_create_snippet"):
                result = fn(request, instance)
                if hasattr(result, "status_code"):
                    return result

            urlquery = ""
            if (isinstance(instance, TranslatableMixin)
                    and instance.locale is not Locale.get_default()):
                urlquery = "?locale=" + instance.locale.language_code

            return redirect(
                reverse("wagtailsnippets:list", args=[app_label, model_name]) +
                urlquery)
        else:
            messages.validation_error(
                request, _("The snippet could not be created due to errors."),
                form)
    else:
        form = form_class(instance=instance)

    edit_handler = edit_handler.bind_to(instance=instance, form=form)

    context = {
        "model_opts": model._meta,
        "edit_handler": edit_handler,
        "form": form,
        "action_menu": SnippetActionMenu(request, view="create", model=model),
        "locale": None,
        "translations": [],
    }

    if getattr(settings, "WAGTAIL_I18N_ENABLED", False) and issubclass(
            model, TranslatableMixin):
        context.update({
            "locale":
            instance.locale,
            "translations": [{
                "locale":
                locale,
                "url":
                reverse("wagtailsnippets:add", args=[app_label, model_name]) +
                "?locale=" + locale.language_code,
            } for locale in Locale.objects.all().exclude(id=instance.locale.id)
                             ],
        })

    return TemplateResponse(request, "wagtailsnippets/snippets/create.html",
                            context)
示例#22
0
def create(request, app_label, model_name):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name('add', model)
    if not request.user.has_perm(permission):
        raise PermissionDenied

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

    instance = model()

    # Set locale of the new instance
    if issubclass(model, TranslatableMixin):
        selected_locale = request.GET.get('locale')
        if selected_locale:
            instance.locale = get_object_or_404(Locale,
                                                language_code=selected_locale)
        else:
            instance.locale = Locale.get_default()

    # Make edit handler
    edit_handler = get_snippet_edit_handler(model)
    edit_handler = edit_handler.bind_to(request=request)
    form_class = edit_handler.get_form_class()

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

        if form.is_valid():
            with transaction.atomic():
                form.save()
                log(instance=instance, action='wagtail.create')

            messages.success(
                request,
                _("%(snippet_type)s '%(instance)s' created.") % {
                    'snippet_type': capfirst(model._meta.verbose_name),
                    'instance': instance
                },
                buttons=[
                    messages.button(
                        reverse('wagtailsnippets:edit',
                                args=(app_label, model_name,
                                      quote(instance.pk))), _('Edit'))
                ])

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

            urlquery = ''
            if isinstance(instance, TranslatableMixin
                          ) and instance.locale is not Locale.get_default():
                urlquery = '?locale=' + instance.locale.language_code

            return redirect(
                reverse('wagtailsnippets:list', args=[app_label, model_name]) +
                urlquery)
        else:
            messages.validation_error(
                request, _("The snippet could not be created due to errors."),
                form)
    else:
        form = form_class(instance=instance)

    edit_handler = edit_handler.bind_to(instance=instance, form=form)

    context = {
        'model_opts': model._meta,
        'edit_handler': edit_handler,
        'form': form,
        'action_menu': SnippetActionMenu(request, view='create', model=model),
        'locale': None,
        'translations': [],
    }

    if getattr(settings, 'WAGTAIL_I18N_ENABLED', False) and issubclass(
            model, TranslatableMixin):
        context.update({
            'locale':
            instance.locale,
            'translations': [{
                'locale':
                locale,
                'url':
                reverse('wagtailsnippets:add', args=[app_label, model_name]) +
                '?locale=' + locale.language_code
            } for locale in Locale.objects.all().exclude(id=instance.locale.id)
                             ],
        })

    return TemplateResponse(request, 'wagtailsnippets/snippets/create.html',
                            context)
示例#23
0
def edit(request, app_label, model_name, pk):
    model = get_snippet_model_from_url_params(app_label, model_name)

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

    instance = get_object_or_404(model, pk=unquote(pk))

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

    edit_handler = get_snippet_edit_handler(model)
    edit_handler = edit_handler.bind_to(instance=instance, request=request)
    form_class = edit_handler.get_form_class()

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

        if form.is_valid():
            with transaction.atomic():
                form.save()
                log(instance=instance, action='wagtail.edit')

            messages.success(
                request,
                _("%(snippet_type)s '%(instance)s' updated.") % {
                    'snippet_type': capfirst(model._meta.verbose_name),
                    'instance': instance
                },
                buttons=[
                    messages.button(
                        reverse('wagtailsnippets:edit',
                                args=(app_label, model_name,
                                      quote(instance.pk))), _('Edit'))
                ])

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

            return redirect('wagtailsnippets:list', app_label, model_name)
        else:
            messages.validation_error(
                request, _("The snippet could not be saved due to errors."),
                form)
    else:
        form = form_class(instance=instance)

    edit_handler = edit_handler.bind_to(form=form)
    latest_log_entry = log_registry.get_logs_for_instance(instance).first()

    context = {
        'model_opts': model._meta,
        'instance': instance,
        'edit_handler': edit_handler,
        'form': form,
        'action_menu': SnippetActionMenu(request,
                                         view='edit',
                                         instance=instance),
        'locale': None,
        'translations': [],
        'latest_log_entry': latest_log_entry,
    }

    if getattr(settings, 'WAGTAIL_I18N_ENABLED', False) and issubclass(
            model, TranslatableMixin):
        context.update({
            'locale':
            instance.locale,
            'translations': [{
                'locale':
                translation.locale,
                'url':
                reverse('wagtailsnippets:edit',
                        args=[app_label, model_name,
                              quote(translation.pk)])
            } for translation in instance.get_translations().select_related(
                'locale')],
        })

    return TemplateResponse(request, 'wagtailsnippets/snippets/edit.html',
                            context)
示例#24
0
    def _move_page(self, page, target, pos=None):
        from wagtail.core.models import Page

        # Determine old and new parents
        parent_before = page.get_parent()
        if pos in ("first-child", "last-child", "sorted-child"):
            parent_after = target
        else:
            parent_after = target.get_parent()

        # Determine old and new url_paths
        # Fetching new object to avoid affecting `page`
        old_page = Page.objects.get(id=page.id)
        old_url_path = old_page.url_path
        new_url_path = old_page.set_url_path(parent=parent_after)
        url_path_changed = old_url_path != new_url_path

        # Emit pre_page_move signal
        pre_page_move.send(
            sender=page.specific_class or page.__class__,
            instance=page,
            parent_page_before=parent_before,
            parent_page_after=parent_after,
            url_path_before=old_url_path,
            url_path_after=new_url_path,
        )

        # Only commit when all descendants are properly updated
        with transaction.atomic():
            # Allow treebeard to update `path` values
            MP_MoveHandler(page, target, pos).process()

            # Treebeard's move method doesn't actually update the in-memory instance,
            # so we need to work with a freshly loaded one now
            new_page = Page.objects.get(id=page.id)
            new_page.url_path = new_url_path
            new_page.save()

            # Update descendant paths if url_path has changed
            if url_path_changed:
                new_page._update_descendant_url_paths(old_url_path,
                                                      new_url_path)

        # Emit post_page_move signal
        post_page_move.send(
            sender=page.specific_class or page.__class__,
            instance=new_page,
            parent_page_before=parent_before,
            parent_page_after=parent_after,
            url_path_before=old_url_path,
            url_path_after=new_url_path,
        )

        # Log
        log(
            instance=page,
            action='wagtail.move' if url_path_changed else 'wagtail.reorder',
            user=self.user,
            data={
                "source": {
                    "id":
                    parent_before.id,
                    "title":
                    parent_before.specific_deferred.get_admin_display_title(),
                },
                "destination": {
                    "id":
                    parent_after.id,
                    "title":
                    parent_after.specific_deferred.get_admin_display_title(),
                },
            },
        )
        logger.info('Page moved: "%s" id=%d path=%s', page.title, page.id,
                    new_url_path)
示例#25
0
文件: account.py 项目: jams2/wagtail
def account(request):
    # Fetch the user and profile objects once and pass into each panel
    # We need to use the same instances for all forms so they don't overwrite each other
    user = request.user
    profile = UserProfile.get_for_user(user)

    # Panels
    panels = [
        NameEmailSettingsPanel(request, user, profile),
        AvatarSettingsPanel(request, user, profile),
        NotificationsSettingsPanel(request, user, profile),
        LocaleSettingsPanel(request, user, profile),
        ChangePasswordPanel(request, user, profile),
    ]
    for fn in hooks.get_hooks("register_account_settings_panel"):
        panel = fn(request, user, profile)
        if panel and panel.is_active():
            panels.append(panel)

    panels = [panel for panel in panels if panel.is_active()]

    # Get tabs and order them
    tabs = list({panel.tab for panel in panels})
    tabs.sort(key=lambda tab: tab.order)

    # Get dict of tabs to ordered panels
    panels_by_tab = OrderedDict([(tab, []) for tab in tabs])
    for panel in panels:
        panels_by_tab[panel.tab].append(panel)
    for tab, tab_panels in panels_by_tab.items():
        tab_panels.sort(key=lambda panel: panel.order)

    panel_forms = [panel.get_form() for panel in panels]

    if request.method == "POST":

        if all(form.is_valid() or not form.is_bound for form in panel_forms):
            with transaction.atomic():
                for form in panel_forms:
                    if form.is_bound:
                        form.save()

            log(user, "wagtail.edit")

            # Prevent a password change from logging this user out
            update_session_auth_hash(request, user)

            # Override the language when creating the success message
            # If the user has changed their language in this request, the message should
            # be in the new language, not the existing one
            with override(profile.get_preferred_language()):
                messages.success(
                    request,
                    _("Your account settings have been changed successfully!"))

            return redirect("wagtailadmin_account")

    media = Media()
    for form in panel_forms:
        media += form.media

    # Menu items
    menu_items = []
    for fn in hooks.get_hooks("register_account_menu_item"):
        item = fn(request)
        if item:
            menu_items.append(item)

    return TemplateResponse(
        request,
        "wagtailadmin/account/account.html",
        {
            "panels_by_tab": panels_by_tab,
            "menu_items": menu_items,
            "media": media,
        },
    )
示例#26
0
    def _create_alias(self, page, *, recursive, parent, update_slug,
                      update_locale, user, log_action, reset_translation_key,
                      _mpnode_attrs):

        specific_page = page.specific

        # FIXME: Switch to the same fields that are excluded from copy
        # We can't do this right now because we can't exclude fields from with_content_json
        # which we use for updating aliases
        exclude_fields = [
            "id",
            "path",
            "depth",
            "numchild",
            "url_path",
            "path",
            "index_entries",
            "postgres_index_entries",
        ]

        update_attrs = {
            "alias_of": page,
            # Aliases don't have revisions so the draft title should always match the live title
            "draft_title": page.title,
            # Likewise, an alias page can't have unpublished changes if it's live
            "has_unpublished_changes": not page.live,
        }

        if update_slug:
            update_attrs["slug"] = update_slug

        if update_locale:
            update_attrs["locale"] = update_locale

        if user:
            update_attrs["owner"] = user

        # When we're not copying for translation, we should give the translation_key a new value
        if reset_translation_key:
            update_attrs["translation_key"] = uuid.uuid4()

        alias, child_object_map = _copy(specific_page,
                                        update_attrs=update_attrs,
                                        exclude_fields=exclude_fields)

        # Update any translatable child objects
        for (child_relation, old_pk), child_object in child_object_map.items():
            if isinstance(child_object, TranslatableMixin):
                if update_locale:
                    child_object.locale = update_locale

                # When we're not copying for translation,
                # we should give the translation_key a new value for each child object as well.
                if reset_translation_key:
                    child_object.translation_key = uuid.uuid4()

        # Save the new page
        if _mpnode_attrs:
            # We've got a tree position already reserved. Perform a quick save.
            alias.path = _mpnode_attrs[0]
            alias.depth = _mpnode_attrs[1]
            alias.save(clean=False)

        else:
            if parent:
                alias = parent.add_child(instance=alias)
            else:
                alias = page.add_sibling(instance=alias)

            _mpnode_attrs = (alias.path, alias.depth)

        _copy_m2m_relations(specific_page,
                            alias,
                            exclude_fields=exclude_fields)

        # Log
        if log_action:
            source_parent = specific_page.get_parent()
            log(
                instance=alias,
                action=log_action,
                user=user,
                data={
                    "page": {
                        "id": alias.id,
                        "title": alias.get_admin_display_title()
                    },
                    "source": {
                        "id":
                        source_parent.id,
                        "title":
                        source_parent.specific_deferred.
                        get_admin_display_title(),
                    } if source_parent else None,
                    "destination": {
                        "id":
                        parent.id,
                        "title":
                        parent.specific_deferred.get_admin_display_title(),
                    } if parent else None,
                },
            )
            if alias.live:
                # Log the publish
                log(
                    instance=alias,
                    action="wagtail.publish",
                    user=user,
                )

        logger.info('Page alias created: "%s" id=%d from=%d', alias.title,
                    alias.id, page.id)

        # Copy child pages
        if recursive:
            from wagtail.core.models import Page

            numchild = 0

            for child_page in page.get_children().specific():
                newdepth = _mpnode_attrs[1] + 1
                child_mpnode_attrs = (
                    Page._get_path(_mpnode_attrs[0], newdepth, numchild),
                    newdepth,
                )
                numchild += 1
                self._create_alias(
                    child_page,
                    recursive=True,
                    parent=alias,
                    update_slug=None,
                    update_locale=update_locale,
                    user=user,
                    log_action=log_action,
                    reset_translation_key=reset_translation_key,
                    _mpnode_attrs=child_mpnode_attrs,
                )

            if numchild > 0:
                alias.numchild = numchild
                alias.save(clean=False, update_fields=["numchild"])

        return alias
示例#27
0
    def _publish_page_revision(self, revision, page, user, changed, log_action,
                               previous_revision):
        from wagtail.core.models import COMMENTS_RELATION_NAME, PageRevision

        if page.go_live_at and page.go_live_at > timezone.now():
            page.has_unpublished_changes = True
            # Instead set the approved_go_live_at of this revision
            revision.approved_go_live_at = page.go_live_at
            revision.save()
            # And clear the the approved_go_live_at of any other revisions
            page.revisions.exclude(id=revision.id).update(
                approved_go_live_at=None)
            # if we are updating a currently live page skip the rest
            if page.live_revision:
                # Log scheduled publishing
                if log_action:
                    self.log_scheduling_action()

                return
            # if we have a go_live in the future don't make the page live
            page.live = False
        else:
            page.live = True
            # at this point, the page has unpublished changes if and only if there are newer revisions than this one
            page.has_unpublished_changes = not revision.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

        # Set first_published_at, last_published_at and live_revision
        # if the page is being published now
        if page.live:
            now = timezone.now()
            page.last_published_at = now
            page.live_revision = revision

            if page.first_published_at is None:
                page.first_published_at = now

            if previous_revision:
                previous_revision_page = previous_revision.as_page_object()
                old_page_title = (previous_revision_page.title
                                  if page.title != previous_revision_page.title
                                  else None)
            else:
                try:
                    previous = revision.get_previous()
                except PageRevision.DoesNotExist:
                    previous = None
                old_page_title = (previous.page.title if previous
                                  and page.title != previous.page.title else
                                  None)
        else:
            # Unset live_revision if the page is going live in the future
            page.live_revision = None

        page.save()

        for comment in getattr(page,
                               COMMENTS_RELATION_NAME).all().only("position"):
            comment.save(update_fields=["position"])

        revision.submitted_for_moderation = False
        page.revisions.update(submitted_for_moderation=False)

        workflow_state = page.current_workflow_state
        if workflow_state and getattr(
                settings, "WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH", True):
            workflow_state.cancel(user=user)

        if page.live:
            page_published.send(sender=page.specific_class,
                                instance=page.specific,
                                revision=revision)

            # Update alias pages
            page.update_aliases(revision=revision,
                                user=user,
                                _content_json=revision.content_json)

            if log_action:
                data = None
                if previous_revision:
                    data = {
                        "revision": {
                            "id":
                            previous_revision.id,
                            "created":
                            previous_revision.created_at.strftime(
                                "%d %b %Y %H:%M"),
                        }
                    }

                if old_page_title:
                    data = data or {}
                    data["title"] = {
                        "old": old_page_title,
                        "new": page.title,
                    }

                    log(
                        instance=page,
                        action="wagtail.rename",
                        user=user,
                        data=data,
                        revision=revision,
                    )

                log(
                    instance=page,
                    action=log_action
                    if isinstance(log_action, str) else "wagtail.publish",
                    user=user,
                    data=data,
                    revision=revision,
                    content_changed=changed,
                )

            logger.info(
                'Page published: "%s" id=%d revision_id=%d',
                page.title,
                page.id,
                revision.id,
            )
        elif page.go_live_at:
            logger.info(
                'Page scheduled for publish: "%s" id=%d revision_id=%d go_live_at=%s',
                page.title,
                page.id,
                revision.id,
                page.go_live_at.isoformat(),
            )

            if log_action:
                self.log_scheduling_action()
示例#28
0
 def form_valid(self, form):
     response = super().form_valid(form)
     log(instance=self.instance, action="wagtail.edit")
     return response
示例#29
0
文件: snippets.py 项目: jams2/wagtail
def delete(request, app_label, model_name, pk=None):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name("delete", model)
    if not request.user.has_perm(permission):
        raise PermissionDenied

    if pk:
        instances = [get_object_or_404(model, pk=unquote(pk))]
    else:
        ids = request.GET.getlist("id")
        instances = model.objects.filter(pk__in=ids)

    for fn in hooks.get_hooks("before_delete_snippet"):
        result = fn(request, instances)
        if hasattr(result, "status_code"):
            return result

    count = len(instances)

    if request.method == "POST":
        with transaction.atomic():
            for instance in instances:
                log(instance=instance, action="wagtail.delete")
                instance.delete()

        if count == 1:
            message_content = _("%(snippet_type)s '%(instance)s' deleted.") % {
                "snippet_type": capfirst(model._meta.verbose_name),
                "instance": instance,
            }
        else:
            # This message is only used in plural form, but we'll define it with ngettext so that
            # languages with multiple plural forms can be handled correctly (or, at least, as
            # correctly as possible within the limitations of verbose_name_plural...)
            message_content = ngettext(
                "%(count)d %(snippet_type)s deleted.",
                "%(count)d %(snippet_type)s deleted.",
                count,
            ) % {
                "snippet_type": capfirst(model._meta.verbose_name_plural),
                "count": count,
            }

        messages.success(request, message_content)

        for fn in hooks.get_hooks("after_delete_snippet"):
            result = fn(request, instances)
            if hasattr(result, "status_code"):
                return result

        return redirect("wagtailsnippets:list", app_label, model_name)

    return TemplateResponse(
        request,
        "wagtailsnippets/snippets/confirm_delete.html",
        {
            "model_opts":
            model._meta,
            "count":
            count,
            "instances":
            instances,
            "submit_url":
            (reverse("wagtailsnippets:delete-multiple",
                     args=(app_label, model_name)) + "?" +
             urlencode([("id", instance.pk) for instance in instances])),
        },
    )
示例#30
0
文件: snippets.py 项目: jams2/wagtail
def edit(request, app_label, model_name, pk):
    model = get_snippet_model_from_url_params(app_label, model_name)

    permission = get_permission_name("change", model)
    if not request.user.has_perm(permission):
        raise PermissionDenied

    instance = get_object_or_404(model, pk=unquote(pk))

    for fn in hooks.get_hooks("before_edit_snippet"):
        result = fn(request, instance)
        if hasattr(result, "status_code"):
            return result

    edit_handler = get_snippet_edit_handler(model)
    edit_handler = edit_handler.bind_to(instance=instance, request=request)
    form_class = edit_handler.get_form_class()

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

        if form.is_valid():
            with transaction.atomic():
                form.save()
                log(instance=instance, action="wagtail.edit")

            messages.success(
                request,
                _("%(snippet_type)s '%(instance)s' updated.") % {
                    "snippet_type": capfirst(model._meta.verbose_name),
                    "instance": instance,
                },
                buttons=[
                    messages.button(
                        reverse(
                            "wagtailsnippets:edit",
                            args=(app_label, model_name, quote(instance.pk)),
                        ),
                        _("Edit"),
                    )
                ],
            )

            for fn in hooks.get_hooks("after_edit_snippet"):
                result = fn(request, instance)
                if hasattr(result, "status_code"):
                    return result

            return redirect("wagtailsnippets:list", app_label, model_name)
        else:
            messages.validation_error(
                request, _("The snippet could not be saved due to errors."),
                form)
    else:
        form = form_class(instance=instance)

    edit_handler = edit_handler.bind_to(form=form)
    latest_log_entry = log_registry.get_logs_for_instance(instance).first()

    context = {
        "model_opts": model._meta,
        "instance": instance,
        "edit_handler": edit_handler,
        "form": form,
        "action_menu": SnippetActionMenu(request,
                                         view="edit",
                                         instance=instance),
        "locale": None,
        "translations": [],
        "latest_log_entry": latest_log_entry,
    }

    if getattr(settings, "WAGTAIL_I18N_ENABLED", False) and issubclass(
            model, TranslatableMixin):
        context.update({
            "locale":
            instance.locale,
            "translations": [{
                "locale":
                translation.locale,
                "url":
                reverse(
                    "wagtailsnippets:edit",
                    args=[app_label, model_name,
                          quote(translation.pk)],
                ),
            } for translation in instance.get_translations().select_related(
                "locale")],
        })

    return TemplateResponse(request, "wagtailsnippets/snippets/edit.html",
                            context)