def test_templates_blogpost_list_related_categories(self):
        """
        The top of the page should list all categories related to at least one of the blog
        posts on the blog posts list page.
        """
        page = PageFactory(
            template="courses/cms/blogpost_list.html",
            title__language="en",
            should_publish=True,
        )

        post1, post2 = BlogPostFactory.create_batch(2,
                                                    page_parent=page,
                                                    should_publish=True)

        category1, category2, category12, category_alone = CategoryFactory.create_batch(
            4, should_publish=True)

        # Attach categories to post1
        placeholder = post1.extended_object.get_public_object(
        ).placeholders.all()[0]
        add_plugin(placeholder,
                   "CategoryPlugin",
                   "en",
                   page=category1.extended_object)
        add_plugin(placeholder,
                   "CategoryPlugin",
                   "en",
                   page=category12.extended_object)

        # Attach categories to post2
        placeholder = post2.extended_object.get_public_object(
        ).placeholders.all()[0]
        add_plugin(placeholder,
                   "CategoryPlugin",
                   "en",
                   page=category2.extended_object)
        add_plugin(placeholder,
                   "CategoryPlugin",
                   "en",
                   page=category12.extended_object)

        response = self.client.get(page.get_absolute_url())
        self.assertEqual(response.status_code, 200)

        for category in [category1, category2, category12]:
            self.assertContains(
                response,
                ('<a class="category-tag" href="{slug:s}">'
                 '<span class="category-tag__title">{title:s}</span>'
                 "</a>").format(
                     slug=category.extended_object.get_absolute_url(),
                     title=category.extended_object.get_title(),
                 ),
                html=True,
            )

        self.assertNotContains(
            response, category_alone.extended_object.get_absolute_url())
    def test_models_blogpost_get_related_blogposts(self):
        """
        Blogposts related via a plugin on the draft page should appear in
        their draft version on the draft page.
        Blogposts related via a plugin on the public page should appear in
        their public version on the public page.
        """
        blogpost1, blogpost2, blogpost3 = BlogPostFactory.create_batch(
            3, should_publish=True
        )
        category = CategoryFactory(should_publish=True)

        # Attach categories
        self._attach_category(blogpost1, category)
        self._attach_category(blogpost2, category)
        self._attach_category(blogpost1.public_extension, category)
        self._attach_category(blogpost3.public_extension, category)

        # Draft blogposts
        with self.assertNumQueries(1):
            self.assertEqual(list(blogpost1.get_related_blogposts()), [blogpost2])
        with self.assertNumQueries(1):
            self.assertEqual(list(blogpost2.get_related_blogposts()), [blogpost1])
        # 2 queries because blogpost3 page fields were not retrieved when attaching categories
        with self.assertNumQueries(2):
            self.assertFalse(blogpost3.get_related_blogposts().exists())

        blogpost1_public = blogpost1.public_extension
        with self.assertNumQueries(1):
            self.assertEqual(
                list(blogpost1_public.get_related_blogposts()),
                [blogpost3.public_extension],
            )

        # Public blogposts
        blogpost2_public = blogpost2.public_extension
        # 2 queries because blogpost2.public_extension page fields were not retrieved when
        # attaching categories
        with self.assertNumQueries(2):
            self.assertFalse(blogpost2_public.get_related_blogposts().exists())

        blogpost3_public = blogpost3.public_extension
        with self.assertNumQueries(1):
            self.assertEqual(
                list(blogpost3_public.get_related_blogposts()),
                [blogpost1.public_extension],
            )
Beispiel #3
0
    def test_models_category_get_blogposts_ordering(self):
        """The related blogposts should be sorted by their position in the pages tree."""
        category = CategoryFactory(should_publish=True)
        blogpost1, blogpost2, blogpost3 = BlogPostFactory.create_batch(
            3, fill_categories=[category], should_publish=True)
        self.assertEqual(list(category.get_blogposts()),
                         [blogpost1, blogpost2, blogpost3])

        # Move pages in the tree and check that they are returned in the new order
        blogpost3.extended_object.move_page(blogpost1.extended_object.node,
                                            position="left")
        self.assertEqual(list(category.get_blogposts()),
                         [blogpost3, blogpost1, blogpost2])

        blogpost1.extended_object.move_page(blogpost3.extended_object.node,
                                            position="left")
        self.assertEqual(list(category.get_blogposts()),
                         [blogpost1, blogpost3, blogpost2])
    def test_models_category_get_blogposts(self):
        """
        It should be possible to retrieve the list of related blogposts on the category
        instance. The number of queries should be minimal.
        """
        category = CategoryFactory(should_publish=True)
        blogposts = BlogPostFactory.create_batch(
            2, page_title="my title", fill_categories=[category], should_publish=True
        )
        retrieved_blogposts = category.get_blogposts()

        with self.assertNumQueries(2):
            self.assertEqual(set(retrieved_blogposts), set(blogposts))

        with self.assertNumQueries(0):
            for blogpost in retrieved_blogposts:
                self.assertEqual(
                    blogpost.extended_object.prefetched_titles[0].title, "my title"
                )
Beispiel #5
0
    def test_models_category_get_blogposts_descendants(self):
        """
        Related blogposts should include the blogposts linked to the category's descendants,
        unless specifically deactivated by the "include_descendants" argument.
        """
        category_page = create_page("Subjects",
                                    "courses/cms/category_detail.html",
                                    "en",
                                    published=True)
        category = CategoryFactory(extended_object=category_page,
                                   should_publish=True)
        blogposts = BlogPostFactory.create_batch(2,
                                                 fill_categories=[category],
                                                 should_publish=True)

        child_category_page = create_page(
            "Literature",
            "courses/cms/category_detail.html",
            "en",
            parent=category_page,
            published=True,
        )
        child_category = CategoryFactory(extended_object=child_category_page,
                                         should_publish=True)
        blogposts_child = BlogPostFactory.create_batch(
            2, fill_categories=[child_category], should_publish=True)

        grand_child_category_page = create_page(
            "Literature",
            "courses/cms/category_detail.html",
            "en",
            parent=child_category_page,
            published=True,
        )
        grand_child_category = CategoryFactory(
            extended_object=grand_child_category_page, should_publish=True)
        blogposts_grand_child = BlogPostFactory.create_batch(
            2, fill_categories=[grand_child_category], should_publish=True)

        # Check that each category gets blogposts from its descendants
        # ...unless we pass an argument to deactivate it
        self.assertEqual(
            list(category.get_blogposts()),
            blogposts + blogposts_child + blogposts_grand_child,
        )
        self.assertEqual(
            list(category.get_blogposts(include_descendants=False)), blogposts)

        self.assertEqual(
            list(child_category.get_blogposts()),
            blogposts_child + blogposts_grand_child,
        )
        self.assertEqual(
            list(child_category.get_blogposts(include_descendants=False)),
            blogposts_child,
        )

        self.assertEqual(
            list(
                grand_child_category.get_blogposts(include_descendants=False)),
            blogposts_grand_child,
        )
        self.assertEqual(list(grand_child_category.get_blogposts()),
                         blogposts_grand_child)
Beispiel #6
0
    def test_models_person_get_blogposts_language_fallback_published(self):
        """
        Validate that the reverse blogposts lookup works as expected with language fallback
        on a published page.
        """
        person1, person2, person3 = PersonFactory.create_batch(
            3, should_publish=True)
        public_person1 = person1.public_extension
        public_person2 = person2.public_extension
        public_person3 = person3.public_extension

        blogpost, blogpost_unpublished = BlogPostFactory.create_batch(
            2, page_languages=["en", "fr", "de"], should_publish=True)

        public_blogpost = blogpost.public_extension

        public_blogpost_unpublished = blogpost_unpublished.public_extension
        blogpost_unpublished.extended_object.unpublish("en")
        blogpost_unpublished.extended_object.unpublish("fr")
        blogpost_unpublished.extended_object.unpublish("de")

        placeholder = public_blogpost.extended_object.placeholders.get(
            slot="author")
        placeholder_unpublished = (
            public_blogpost_unpublished.extended_object.placeholders.get(
                slot="author"))
        # Reverse plugin lookups should fallback up to the second priority language
        add_plugin(
            language="de",
            placeholder=placeholder,
            plugin_type="PersonPlugin",
            **{"page": person1.extended_object},
        )
        add_plugin(
            language="de",
            placeholder=placeholder_unpublished,
            plugin_type="PersonPlugin",
            **{"page": person1.extended_object},
        )

        with translation.override("en"):
            self.assertEqual(list(public_person1.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        with translation.override("fr"):
            self.assertEqual(list(public_person1.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        with translation.override("de"):
            self.assertEqual(list(public_person1.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        # Reverse plugin lookups should fallback to the first priority language if available
        # and ignore the second priority language unless it is the current language
        add_plugin(
            language="fr",
            placeholder=placeholder,
            plugin_type="PersonPlugin",
            **{"page": person2.extended_object},
        )
        add_plugin(
            language="fr",
            placeholder=placeholder_unpublished,
            plugin_type="PersonPlugin",
            **{"page": person2.extended_object},
        )
        with translation.override("en"):
            self.assertEqual(list(public_person1.get_blogposts()), [])
            self.assertEqual(list(public_person2.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        with translation.override("fr"):
            self.assertEqual(list(public_person1.get_blogposts()), [])
            self.assertEqual(list(public_person2.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        with translation.override("de"):
            self.assertEqual(list(public_person1.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        # Reverse plugin lookups should stick to the current language if available and
        # ignore plugins on fallback languages
        add_plugin(
            language="en",
            placeholder=placeholder,
            plugin_type="PersonPlugin",
            **{"page": person3.extended_object},
        )
        add_plugin(
            language="en",
            placeholder=placeholder_unpublished,
            plugin_type="PersonPlugin",
            **{"page": person3.extended_object},
        )
        with translation.override("en"):
            self.assertEqual(list(public_person1.get_blogposts()), [])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()),
                             [public_blogpost])

        with translation.override("fr"):
            self.assertEqual(list(public_person1.get_blogposts()), [])
            self.assertEqual(list(public_person2.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person3.get_blogposts()), [])

        with translation.override("de"):
            self.assertEqual(list(public_person1.get_blogposts()),
                             [public_blogpost])
            self.assertEqual(list(public_person2.get_blogposts()), [])
            self.assertEqual(list(public_person3.get_blogposts()), [])