Exemplo n.º 1
0
 def test_change_root_page_locale_on_locale_deletion(self):
     """
     On deleting the locale used for the root page (but no 'real' pages), the
     root page should be reassigned to a new locale (the default one, if possible)
     """
     # change 'real' pages first
     Page.objects.filter(depth__gt=1).update(locale=Locale.objects.get(
         language_code="fr"))
     self.assertEqual(Page.get_first_root_node().locale.language_code, "en")
     Locale.objects.get(language_code="en").delete()
     self.assertEqual(Page.get_first_root_node().locale.language_code, "fr")
Exemplo n.º 2
0
    def test_construct_queryset_hook(self):
        page = SimplePage(title="Test shown", content="hello")
        Page.get_first_root_node().add_child(instance=page)

        page_not_shown = SimplePage(title="Test not shown", content="hello")
        Page.get_first_root_node().add_child(instance=page_not_shown)

        def filter_pages(pages, request):
            return pages.filter(id=page.id)

        with self.register_hook("construct_page_chooser_queryset",
                                filter_pages):
            response = self.get()
        self.assertEqual(len(response.context["pages"]), 1)
        self.assertEqual(response.context["pages"][0].specific, page)
Exemplo n.º 3
0
    def test_can_delete_default_locale_when_language_code_has_no_locale(self):
        Locale.objects.create(language_code="fr")

        self.assertTrue(Page.get_first_root_node().locale.language_code, "en")
        Page.objects.filter(depth__gt=1).delete()
        response = self.post()

        # Should redirect back to index
        self.assertRedirects(response, reverse("wagtaillocales:index"))

        # Check that the locale was deleted
        self.assertFalse(Locale.objects.filter(language_code="en").exists())

        # root node's locale should now have been reassigned to 'fr' despite that not matching
        # LANGUAGE_CODE (because it's the only remaining Locale record)
        self.assertTrue(Page.get_first_root_node().locale.language_code, "fr")
Exemplo n.º 4
0
    def setUpClass(cls):
        super().setUpClass()

        cls.test_page = SimplePage(title="test", slug="test", content="test")
        cls.wagtail_root = Page.get_first_root_node()
        cls.wagtail_root.add_child(instance=cls.test_page)

        cls.test_page_group = Group.objects.create(name="Test page")
        GroupPagePermission.objects.create(
            group=cls.test_page_group, page=cls.test_page, permission_type="edit"
        )
Exemplo n.º 5
0
    def test_can_delete_default_locale(self):
        # The presence of the locale on the root page node (if that's the only thing using the
        # locale) should not prevent deleting it

        for lang in ("fr", "de", "pl", "ja"):
            Locale.objects.create(language_code=lang)

        self.assertTrue(Page.get_first_root_node().locale.language_code, "en")
        Page.objects.filter(depth__gt=1).delete()
        response = self.post()

        # Should redirect back to index
        self.assertRedirects(response, reverse("wagtaillocales:index"))

        # Check that the locale was deleted
        self.assertFalse(Locale.objects.filter(language_code="en").exists())

        # root node's locale should now have been reassigned to the one matching the current
        # LANGUAGE_CODE
        self.assertTrue(Page.get_first_root_node().locale.language_code, "de")
Exemplo n.º 6
0
    def setUp(self):
        self.site_2_page = SimplePage(
            title="Site 2 page",
            slug="site_2_page",
            content="Hello",
        )
        Page.get_first_root_node().add_child(instance=self.site_2_page)
        self.site_2_subpage = SimplePage(
            title="Site 2 subpage",
            slug="site_2_subpage",
            content="Hello again",
        )
        self.site_2_page.add_child(instance=self.site_2_subpage)

        self.site_2 = Site.objects.create(
            hostname="example.com",
            port=8080,
            root_page=Page.objects.get(pk=self.site_2_page.pk),
            is_default_site=False,
        )
        self.about_us_page = SimplePage.objects.get(url_path="/home/about-us/")
Exemplo n.º 7
0
    def _setup(self):
        Page.objects.filter(id=2).delete()
        root = Page.get_first_root_node()
        homepage = HomePage(
            title="St Louis DSA",
            banner_title="Welcome to St Louis DSA!",
            mission_statement=fake.sentence(10),
            values_statement=fake.sentence(10),
            highlighted_campaign=f"{' '.join(fake.words(2)).title()} Campaign",
            highlighted_description=fake.paragraph(5),
        )
        root.add_child(instance=homepage)
        site = Site(
            hostname="localhost",
            root_page=homepage,
            is_default_site=True,
            site_name="stldsa.org",
        )
        site.save()

        newsindexpage = NewsIndexPage(
            title="Updates",
            slug="updates",
            show_in_menus=True,
        )
        homepage.add_child(instance=newsindexpage)
        newsindexpage.has_children_in_menu = False
        newsindexpage.sub_menu = None

        NewsPage = apps.get_model("news.NewsPage")
        newspage = NewsPage(
            title=fake.sentence(),
            main_story_heading=fake.sentence(),
            main_story_copy=fake.paragraph(10),
            related_stories=[
                (
                    "related_story",
                    {
                        "heading": fake.sentence(4),
                        "copy": fake.paragraph(5),
                    },
                ),
                (
                    "related_story",
                    {
                        "heading": fake.sentence(4),
                        "copy": fake.paragraph(4),
                    },
                ),
            ],
            show_in_menus=False,
        )
        newsindexpage.add_child(instance=newspage)

        event_menu_page = EventsPage(title="Events",
                                     show_in_menus=True,
                                     link_url="/events/")
        homepage.add_child(instance=event_menu_page)
        formation_index = InfoPage(title="All Formation Groups",
                                   show_in_menus=True)
        homepage.add_child(instance=formation_index)
        for formation_type_name in [
                "Priority Resolutions",
                "Committees",
                "Working Groups",
                "Caucuses",
        ]:
            formation_type = CommitteesPage(
                title=formation_type_name,
                slug=stringcase.spinalcase(formation_type_name),
                show_in_menus=True,
            )
            formation_index.add_child(instance=formation_type)
            formation_list = CommitteeFactory.build_batch(4)
            for formation in formation_list:
                formation_type.add_child(instance=formation)
                revision = formation.save_revision()
                revision.publish()
                formation.save()

                future_event = Event(
                    title="Event Title",
                    description=fake.paragraph(),
                    start=fake.future_datetime(
                        end_date=datetime.timedelta(days=6),
                        tzinfo=datetime.timezone.utc,
                    ),
                    formation=formation,
                )
                future_event.save()

            revision = formation_type.save_revision()
            revision.publish()
            formation_type.save()
        formation_index.save()

        Group.objects.create(name="Members")
Exemplo n.º 8
0
def browse(request, parent_page_id=None):
    # A missing or empty page_type parameter indicates 'all page types'
    # (i.e. descendants of wagtailcore.page)
    page_type_string = request.GET.get("page_type") or "wagtailcore.page"
    user_perm = request.GET.get("user_perms", False)

    try:
        desired_classes = page_models_from_string(page_type_string)
    except (ValueError, LookupError):
        raise Http404

    # Find parent page
    if parent_page_id:
        parent_page = get_object_or_404(Page, id=parent_page_id)
    elif desired_classes == (Page, ):
        # Just use the root page
        parent_page = Page.get_first_root_node()
    else:
        # Find the highest common ancestor for the specific classes passed in
        # In many cases, such as selecting an EventPage under an EventIndex,
        # this will help the administrator find their page quicker.
        all_desired_pages = Page.objects.all().type(*desired_classes)
        parent_page = all_desired_pages.first_common_ancestor()

    parent_page = parent_page.specific

    # Get children of parent page (without streamfields)
    pages = parent_page.get_children().defer_streamfields().specific()

    # allow hooks to modify the queryset
    for hook in hooks.get_hooks("construct_page_chooser_queryset"):
        pages = hook(pages, request)

    # Filter them by page type
    if desired_classes != (Page, ):
        # restrict the page listing to just those pages that:
        # - are of the given content type (taking into account class inheritance)
        # - or can be navigated into (i.e. have children)
        choosable_pages = pages.type(*desired_classes)
        descendable_pages = pages.filter(numchild__gt=0)
        pages = choosable_pages | descendable_pages

    can_choose_root = request.GET.get("can_choose_root", False)
    target_pages = Page.objects.filter(pk__in=[
        int(pk) for pk in request.GET.getlist("target_pages[]", []) if pk
    ])

    match_subclass = request.GET.get("match_subclass", True)

    # Do permission lookups for this user now, instead of for every page.
    permission_proxy = UserPagePermissionsProxy(request.user)

    # Parent page can be chosen if it is a instance of desired_classes
    parent_page.can_choose = can_choose_page(
        parent_page,
        permission_proxy,
        desired_classes,
        can_choose_root,
        user_perm,
        target_pages=target_pages,
        match_subclass=match_subclass,
    )
    parent_page.is_parent_page = True
    parent_page.can_descend = False

    selected_locale = None
    locale_options = []
    show_locale_labels = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
    if show_locale_labels:
        pages = pages.select_related("locale")

        if parent_page.is_root():
            # 'locale' is the current value of the "Locale" selector in the UI
            if request.GET.get("locale"):
                selected_locale = get_object_or_404(
                    Locale, language_code=request.GET["locale"])
                active_locale_id = selected_locale.pk
            else:
                active_locale_id = Locale.get_active().pk

            # we are at the Root level, so get the locales from the current pages
            choose_url = reverse("wagtailadmin_choose_page")
            locale_options = [{
                "locale":
                locale,
                "url":
                choose_url + "?" + urlencode({
                    "page_type": page_type_string,
                    "locale": locale.language_code
                }),
            } for locale in Locale.objects.filter(
                pk__in=pages.values_list("locale_id")).exclude(
                    pk=active_locale_id)]
        else:
            # We have a parent page (that is not the root page). Use its locale as the selected localer
            selected_locale = parent_page.locale
            # and get the locales based on its available translations
            locales_and_parent_pages = {
                item["locale"]: item["pk"]
                for item in Page.objects.translation_of(parent_page).values(
                    "locale", "pk")
            }
            locales_and_parent_pages[selected_locale.pk] = parent_page.pk
            for locale in Locale.objects.filter(
                    pk__in=list(locales_and_parent_pages.keys())).exclude(
                        pk=selected_locale.pk):
                choose_child_url = reverse(
                    "wagtailadmin_choose_page_child",
                    args=[locales_and_parent_pages[locale.pk]],
                )

                locale_options.append({
                    "locale":
                    locale,
                    "url":
                    choose_child_url + "?" +
                    urlencode({"page_type": page_type_string}),
                })

        # finally, filter the browseable pages on the selected locale
        if selected_locale:
            pages = pages.filter(locale=selected_locale)

    # Pagination
    # We apply pagination first so we don't need to walk the entire list
    # in the block below
    paginator = Paginator(pages, per_page=25)
    pages = paginator.get_page(request.GET.get("p"))

    # Annotate each page with can_choose/can_decend flags
    for page in pages:
        page.can_choose = can_choose_page(
            page,
            permission_proxy,
            desired_classes,
            can_choose_root,
            user_perm,
            target_pages=target_pages,
            match_subclass=match_subclass,
        )
        page.can_descend = page.get_children_count()
        page.is_parent_page = False

    table = PageChooserTable(
        [
            PageTitleColumn("title", label=_("Title")),
            DateColumn(
                "updated",
                label=_("Updated"),
                width="12%",
                accessor="latest_revision_created_at",
            ),
            Column("type",
                   label=_("Type"),
                   width="12%",
                   accessor="page_type_display_name"),
            PageStatusColumn("status", label=_("Status"), width="12%"),
            PageNavigateToChildrenColumn("children", label="", width="10%"),
        ],
        [parent_page] + list(pages),
    )

    # Render
    context = shared_context(
        request,
        {
            "parent_page":
            parent_page,
            "parent_page_id":
            parent_page.pk,
            "table":
            table,
            "pagination_page":
            pages,
            "search_form":
            SearchForm(),
            "page_type_string":
            page_type_string,
            "page_type_names": [
                desired_class.get_verbose_name()
                for desired_class in desired_classes
            ],
            "page_types_restricted": (page_type_string != "wagtailcore.page"),
            "show_locale_labels":
            show_locale_labels,
            "locale_options":
            locale_options,
            "selected_locale":
            selected_locale,
        },
    )

    return render_modal_workflow(
        request,
        "wagtailadmin/chooser/browse.html",
        None,
        context,
        json_data={
            "step": "browse",
            "parent_page_id": context["parent_page_id"]
        },
    )
Exemplo n.º 9
0
 def get_root_page(self):
     """
     Returns the page that is used when the `&child_of=root` filter is used.
     """
     return Page.get_first_root_node()
Exemplo n.º 10
0
 def test_empty_queryset(self):
     self.assertEqual(Page.get_first_root_node(),
                      Page.objects.none().first_common_ancestor())
Exemplo n.º 11
0
 def test_all_pages_include_self_strict(self):
     self.assertEqual(
         Page.get_first_root_node(),
         Page.objects.first_common_ancestor(include_self=True, strict=True),
     )
Exemplo n.º 12
0
 def test_all_pages(self):
     self.assertEqual(Page.get_first_root_node(),
                      Page.objects.first_common_ancestor())
Exemplo n.º 13
0
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()

    # This will always succeed because of the @user_passes_test above.
    root_page = get_explorable_root_page(request.user)

    # If this page isn't a descendant of the user's explorable root page,
    # then redirect to that explorable root page instead.
    if not (parent_page.pk == root_page.pk
            or parent_page.is_descendant_of(root_page)):
        return redirect("wagtailadmin_explore", root_page.pk)

    parent_page = parent_page.specific

    user_perms = UserPagePermissionsProxy(request.user)
    pages = (parent_page.get_children().prefetch_related(
        "content_type", "sites_rooted_here")
             & user_perms.explorable_pages())

    # 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"

    if ordering == "ord":
        # preserve the native ordering from get_children()
        pass
    elif ordering == "latest_revision_created_at":
        # order by oldest revision first.
        # Special case NULL entries - these should go at the top of the list.
        # Do this by annotating with Count('latest_revision_created_at'),
        # which returns 0 for these
        pages = pages.annotate(
            null_position=Count("latest_revision_created_at")).order_by(
                "null_position", "latest_revision_created_at")
    elif ordering == "-latest_revision_created_at":
        # order by oldest revision first.
        # Special case NULL entries - these should go at the end of the list.
        pages = pages.annotate(
            null_position=Count("latest_revision_created_at")).order_by(
                "-null_position", "-latest_revision_created_at")
    else:
        pages = pages.order_by(ordering)

    # Don't paginate if sorting by page order - all pages must be shown to
    # allow drag-and-drop reordering
    do_paginate = ordering != "ord"

    # We want specific page instances, but do not need streamfield values here
    pages = pages.defer_streamfields().specific()

    # allow hooks defer_streamfieldsyset
    for hook in hooks.get_hooks("construct_explorer_page_queryset"):
        pages = hook(parent_page, pages, request)

    # Annotate queryset with various states to be used later for performance optimisations
    if getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
        pages = pages.prefetch_workflow_states()

    pages = pages.annotate_site_root_state().annotate_approved_schedule()

    # Pagination
    if do_paginate:
        paginator = Paginator(pages, per_page=50)
        pages = paginator.get_page(request.GET.get("p"))

    show_ordering_column = request.GET.get("ordering") == "ord"

    context = {
        "parent_page": parent_page.specific,
        "ordering": ordering,
        "pages": pages,
        "do_paginate": do_paginate,
        "locale": None,
        "translations": [],
        "show_ordering_column": show_ordering_column,
        "show_bulk_actions": not show_ordering_column,
        "show_locale_labels": False,
    }

    if getattr(settings, "WAGTAIL_I18N_ENABLED", False):
        if not parent_page.is_root():
            context.update({
                "locale":
                parent_page.locale,
                "translations": [{
                    "locale":
                    translation.locale,
                    "url":
                    reverse("wagtailadmin_explore", args=[translation.id]),
                } for translation in parent_page.get_translations().only(
                    "id", "locale").select_related("locale")],
            })
        else:
            context["show_locale_labels"] = True

    return TemplateResponse(request, "wagtailadmin/pages/index.html", context)
Exemplo n.º 14
0
 def get_form_kwargs(self):
     ctx = super().get_form_kwargs()
     ctx["destination"] = self.destination or Page.get_first_root_node()
     ctx["target_parent_models"] = self.target_parent_models
     ctx["pages_to_move"] = self.pages_to_move
     return ctx
Exemplo n.º 15
0
    def get(self, request, parent_page_id=None):
        self.i18n_enabled = getattr(settings, "WAGTAIL_I18N_ENABLED", False)

        # A missing or empty page_type parameter indicates 'all page types'
        # (i.e. descendants of wagtailcore.page)
        page_type_string = request.GET.get("page_type") or "wagtailcore.page"
        user_perm = request.GET.get("user_perms", False)

        try:
            self.desired_classes = page_models_from_string(page_type_string)
        except (ValueError, LookupError):
            raise Http404

        # Find parent page
        if parent_page_id:
            self.parent_page = get_object_or_404(Page, id=parent_page_id)
        elif self.desired_classes == (Page, ):
            # Just use the root page
            self.parent_page = Page.get_first_root_node()
        else:
            # Find the highest common ancestor for the specific classes passed in
            # In many cases, such as selecting an EventPage under an EventIndex,
            # this will help the administrator find their page quicker.
            all_desired_pages = Page.objects.all().type(*self.desired_classes)
            self.parent_page = all_desired_pages.first_common_ancestor()

        self.parent_page = self.parent_page.specific

        pages = self.get_object_list()
        pages = self.filter_object_list(pages)

        can_choose_root = request.GET.get("can_choose_root", False)
        target_pages = Page.objects.filter(pk__in=[
            int(pk) for pk in request.GET.getlist("target_pages[]", []) if pk
        ])

        match_subclass = request.GET.get("match_subclass", True)

        # Do permission lookups for this user now, instead of for every page.
        permission_proxy = UserPagePermissionsProxy(request.user)

        # Parent page can be chosen if it is a instance of desired_classes
        self.parent_page.can_choose = can_choose_page(
            self.parent_page,
            permission_proxy,
            self.desired_classes,
            can_choose_root,
            user_perm,
            target_pages=target_pages,
            match_subclass=match_subclass,
        )
        self.parent_page.is_parent_page = True
        self.parent_page.can_descend = False

        selected_locale = None
        locale_options = []
        if self.i18n_enabled:
            if self.parent_page.is_root():
                # 'locale' is the current value of the "Locale" selector in the UI
                if request.GET.get("locale"):
                    selected_locale = get_object_or_404(
                        Locale, language_code=request.GET["locale"])
                    active_locale_id = selected_locale.pk
                else:
                    active_locale_id = Locale.get_active().pk

                # we are at the Root level, so get the locales from the current pages
                choose_url = reverse("wagtailadmin_choose_page")
                locale_options = [{
                    "locale":
                    locale,
                    "url":
                    choose_url + "?" +
                    urlencode({
                        "page_type": page_type_string,
                        "locale": locale.language_code,
                    }),
                } for locale in Locale.objects.filter(
                    pk__in=pages.values_list("locale_id")).exclude(
                        pk=active_locale_id)]
            else:
                # We have a parent page (that is not the root page). Use its locale as the selected localer
                selected_locale = self.parent_page.locale
                # and get the locales based on its available translations
                locales_and_parent_pages = {
                    item["locale"]: item["pk"]
                    for item in Page.objects.translation_of(
                        self.parent_page).values("locale", "pk")
                }
                locales_and_parent_pages[
                    selected_locale.pk] = self.parent_page.pk
                for locale in Locale.objects.filter(
                        pk__in=list(locales_and_parent_pages.keys())).exclude(
                            pk=selected_locale.pk):
                    choose_child_url = reverse(
                        "wagtailadmin_choose_page_child",
                        args=[locales_and_parent_pages[locale.pk]],
                    )

                    locale_options.append({
                        "locale":
                        locale,
                        "url":
                        choose_child_url + "?" +
                        urlencode({"page_type": page_type_string}),
                    })

            # finally, filter the browseable pages on the selected locale
            if selected_locale:
                pages = pages.filter(locale=selected_locale)

        # Pagination
        # We apply pagination first so we don't need to walk the entire list
        # in the block below
        paginator = Paginator(pages, per_page=25)
        pages = paginator.get_page(request.GET.get("p"))

        # Annotate each page with can_choose/can_decend flags
        for page in pages:
            page.can_choose = can_choose_page(
                page,
                permission_proxy,
                self.desired_classes,
                can_choose_root,
                user_perm,
                target_pages=target_pages,
                match_subclass=match_subclass,
            )
            page.can_descend = page.get_children_count()
            page.is_parent_page = False

        table = PageChooserTable(
            self.columns,
            [self.parent_page] + list(pages),
        )

        # Render
        context = shared_context(
            request,
            {
                "parent_page":
                self.parent_page,
                "parent_page_id":
                self.parent_page.pk,
                "table":
                table,
                "pagination_page":
                pages,
                "search_form":
                SearchForm(),
                "page_type_string":
                page_type_string,
                "page_type_names": [
                    desired_class.get_verbose_name()
                    for desired_class in self.desired_classes
                ],
                "page_types_restricted":
                (page_type_string != "wagtailcore.page"),
                "show_locale_labels":
                self.i18n_enabled,
                "locale_options":
                locale_options,
                "selected_locale":
                selected_locale,
            },
        )

        return render_modal_workflow(
            request,
            "wagtailadmin/chooser/browse.html",
            None,
            context,
            json_data={
                "step": "browse",
                "parent_page_id": context["parent_page_id"]
            },
        )