Пример #1
0
def create_demo_site():
    """
    Create a simple site tree structure for developpers to work in realistic environment.

    We create multilingual pages, add organizations under the related page and add
    plugins to each page.
    """
    site = Site.objects.get(id=1)

    # Create pages as described in PAGES_INFOS
    pages_created = recursive_page_creation(site, PAGES_INFO)

    # Create the footer links
    footer_static_ph = StaticPlaceholder.objects.get_or_create(code="footer")[0]
    for footer_placeholder in [footer_static_ph.draft, footer_static_ph.public]:
        for language, content in FOOTER_CONTENT.items():
            # Create the <ul> section to carry the list of links
            section_plugin = add_plugin(
                footer_placeholder,
                plugin_type="SectionPlugin",
                language=language,
                template="richie/section/section_list.html",
            )

            # One column per content object
            for footer_info in content:
                column_plugin = add_plugin(
                    footer_placeholder,
                    plugin_type="SectionPlugin",
                    language=language,
                    target=section_plugin,
                    template="richie/section/section_list.html",
                    title=footer_info.get("title"),
                )
                for item_info in footer_info.get("items", []):
                    if "internal_link" in item_info:
                        item_info = item_info.copy()
                        item_info["internal_link"] = pages_created[
                            item_info["internal_link"]
                        ]
                    add_plugin(
                        footer_placeholder,
                        plugin_type="LinkPlugin",
                        language=language,
                        target=column_plugin,
                        **item_info,
                    )

    # Create some licences
    licences = LicenceFactory.create_batch(
        NB_OBJECTS["licences"], logo__file__from_path=pick_image("licence")()
    )

    # Generate each category tree and return a list of the leaf categories
    icons = list(
        create_categories(
            **ICONS_INFO,
            fill_banner=pick_image("banner"),
            fill_logo=pick_image("logo"),
            page_parent=pages_created["categories"],
        )
    )
    levels = list(
        create_categories(
            **LEVELS_INFO,
            fill_banner=pick_image("banner"),
            fill_logo=pick_image("logo"),
            page_parent=pages_created["categories"],
        )
    )
    subjects = list(
        create_categories(
            **SUBJECTS_INFO,
            fill_banner=pick_image("banner"),
            fill_logo=pick_image("logo"),
            page_parent=pages_created["categories"],
        )
    )
    partnerships = list(
        create_categories(
            **PARTNERSHIPS_INFO,
            fill_banner=pick_image("banner"),
            fill_logo=pick_image("logo"),
            page_parent=pages_created["categories"],
        )
    )

    # Create organizations under the `Organizations` page
    organizations = []
    for i in range(NB_OBJECTS["organizations"]):
        # Randomly assign each organization to a partnership level category
        organizations.append(
            OrganizationFactory(
                page_in_navigation=True,
                page_languages=["en", "fr"],
                page_parent=pages_created["organizations"],
                fill_banner=pick_image("banner"),
                fill_categories=[random.choice(partnerships)]  # nosec
                if (i % 2 == 0)
                else [],
                fill_description=True,
                fill_logo=pick_image("logo"),
                should_publish=True,
                with_permissions=True,
            )
        )

    # Create persons under the `persons` page
    persons = []
    persons_for_organization = defaultdict(list)
    for _ in range(NB_OBJECTS["persons"]):
        # Randomly assign each person to a set of organizations
        person_organizations = random.sample(
            organizations,
            random.randint(1, NB_OBJECTS["person_organizations"]),  # nosec
        )
        person = PersonFactory(
            page_in_navigation=True,
            page_languages=["en", "fr"],
            page_parent=pages_created["persons"],
            fill_categories=random.sample(
                subjects, random.randint(1, NB_OBJECTS["person_subjects"])  # nosec
            ),
            fill_organizations=person_organizations,
            fill_portrait=pick_image("portrait"),
            fill_bio=True,
            should_publish=True,
        )
        persons.append(person)
        for organization in person_organizations:
            persons_for_organization[organization.id].append(person)

    # Assign each person randomly to an organization so that our course are tagged realistically
    # If organizations and persons are tagged randomly on courses, each organizations will
    # in the end be related to most persons... not what we want.

    # Create courses under the `Course` page with categories and organizations
    # relations
    courses = []
    for _ in range(NB_OBJECTS["courses"]):
        video_sample = random.choice(VIDEO_SAMPLE_LINKS)  # nosec

        # Randomly assign each course to a set of organizations
        course_organizations = random.sample(
            organizations, NB_OBJECTS["course_organizations"]
        )

        # Only the persons members of these organizations are eligible to be part
        # of the course team
        eligible_persons = set(
            person
            for o in course_organizations
            for person in persons_for_organization[o.id]
        )

        course = CourseFactory(
            page_in_navigation=True,
            page_languages=["en", "fr"],
            page_parent=pages_created["courses"],
            fill_licences=[
                ("course_license_content", random.choice(licences)),  # nosec
                ("course_license_participation", random.choice(licences)),  # nosec
            ],
            fill_team=random.sample(
                eligible_persons,
                min(
                    random.randint(1, NB_OBJECTS["course_persons"]),  # nosec
                    len(eligible_persons),
                ),
            ),
            fill_teaser=video_sample,
            fill_cover=pick_image("cover")(video_sample.image),
            fill_categories=[
                *random.sample(
                    subjects, random.randint(1, NB_OBJECTS["course_subjects"])  # nosec
                ),
                random.choice(levels),  # nosec
            ],
            fill_icons=random.sample(icons, get_number_of_icons()),
            fill_organizations=course_organizations,
            fill_texts=[
                "course_description",
                "course_format",
                "course_prerequisites",
                "course_plan",
                # "course_license_content",
                # "course_license_participation",
            ],
            should_publish=True,
        )
        course.create_permissions_for_organization(course_organizations[0])
        courses.append(course)

        # Add a random number of course runs to the course
        nb_course_runs = get_number_of_course_runs()
        # pick a subset of languages for this course (otherwise all courses will have more or
        # less all the languages across their course runs!)
        languages_subset = random.sample(
            ["de", "en", "es", "fr", "it", "nl"], random.randint(1, 4)  # nosec
        )
        for i in range(nb_course_runs):
            CourseRunFactory(
                __sequence=i,
                languages=random.sample(
                    languages_subset, random.randint(1, len(languages_subset))  # nosec
                ),
                page_in_navigation=False,
                page_languages=["en", "fr"],
                page_parent=course.extended_object,
                should_publish=True,
            )

    # Create blog posts under the `News` page
    blogposts = []
    for _ in range(NB_OBJECTS["blogposts"]):
        post = BlogPostFactory.create(
            page_in_navigation=True,
            page_languages=["en", "fr"],
            page_parent=pages_created["blogposts"],
            fill_cover=pick_image("cover"),
            fill_excerpt=True,
            fill_body=True,
            fill_categories=[
                *random.sample(subjects, NB_OBJECTS["blogpost_categories"]),
                random.choice(levels),  # nosec
            ],
            fill_author=random.sample(persons, 1),
            should_publish=True,
        )
        blogposts.append(post)

    # Create programs under the `Programs` page
    programs = []
    for _ in range(NB_OBJECTS["programs"]):
        program = ProgramFactory.create(
            page_in_navigation=True,
            page_languages=["en", "fr"],
            page_parent=pages_created["programs"],
            fill_cover=pick_image("cover"),
            fill_excerpt=True,
            fill_body=True,
            fill_courses=[*random.sample(courses, NB_OBJECTS["programs_courses"])],
            should_publish=True,
        )
        programs.append(program)

    # Once everything has been created, use some content to create a homepage
    placeholder = pages_created["home"].placeholders.get(slot="maincontent")

    # - Get a banner image
    banner = image_getter(pick_image("banner")())

    # - Get a logo image
    logo = image_getter(pick_image("logo")())

    # - Create the home page in each language
    for language, content in HOMEPAGE_CONTENT.items():
        # Add a banner
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LargeBannerPlugin",
            title=content["banner_title"],
            background_image=banner,
            logo=logo,
            logo_alt_text="logo",
            content=content["banner_content"],
            template=content["banner_template"],
        )
        # Add highlighted courses with a button
        courses_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["courses_title"],
            template=content["section_template"],
        )
        for course in random.sample(courses, NB_OBJECTS["home_courses"]):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="CoursePlugin",
                target=courses_section,
                page=course.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=courses_section,
            name=content["courses_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["courses"],
        )

        # Add highlighted blogposts
        blogposts_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["blogposts_title"],
            template=content["section_template"],
        )
        for blogpost in random.sample(blogposts, NB_OBJECTS["home_blogposts"]):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="BlogPostPlugin",
                target=blogposts_section,
                page=blogpost.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=blogposts_section,
            name=content["blogposts_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["blogposts"],
        )

        # Add highlighted programs
        programs_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["programs_title"],
            template=content["section_template"],
        )
        for program in random.sample(programs, NB_OBJECTS["home_programs"]):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="ProgramPlugin",
                target=programs_section,
                page=program.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=programs_section,
            name=content["programs_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["programs"],
        )

        # Add highlighted organizations
        organizations_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["organizations_title"],
            template=content["section_template"],
        )
        for organization in random.sample(
            organizations, NB_OBJECTS["home_organizations"]
        ):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="OrganizationPlugin",
                target=organizations_section,
                page=organization.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=organizations_section,
            name=content["organizations_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["organizations"],
        )

        # Add highlighted subjects
        subjects_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["subjects_title"],
            template=content["section_template"],
        )
        for subject in random.sample(subjects, NB_OBJECTS["home_subjects"]):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="CategoryPlugin",
                target=subjects_section,
                page=subject.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=subjects_section,
            name=content["subjects_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["categories"],
        )

        # Add highlighted persons
        persons_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["persons_title"],
            template=content["section_template"],
        )
        for person in random.sample(persons, NB_OBJECTS["home_persons"]):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="PersonPlugin",
                target=persons_section,
                page=person.extended_object,
            )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=persons_section,
            name=content["persons_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["persons"],
        )

        # Once content has been added we must publish again homepage
        pages_created["home"].publish(language)

    # Fill the single column sample page
    placeholder = pages_created["annex__about"].placeholders.get(slot="maincontent")

    # - Get a banner image
    banner = image_getter(pick_image("banner")())

    # - Get a logo image
    logo = image_getter(pick_image("logo")())

    # - Get a video
    video_sample = random.choice(VIDEO_SAMPLE_LINKS)  # nosec

    # - Create sample page in each language
    for language, content in SINGLECOLUMN_CONTENT.items():
        # Add a banner
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LargeBannerPlugin",
            title=content["banner_title"],
            background_image=banner,
            content=content["banner_content"],
            template=content["banner_template"],
        )
        # HTML paragraphs
        create_text_plugin(
            pages_created["annex__about"],
            placeholder,
            nb_paragraphs=random.randint(3, 4),  # nosec
            languages=[language],
            plugin_type="TextPlugin",
        )
        # A large video sample
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="VideoPlayerPlugin",
            label=video_sample.label,
            embed_link=video_sample.url,
            template="full-width",
        )
        # Section with some various plugins
        sample_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["section_sample_title"],
            template=content["section_sample_template"],
        )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="OrganizationPlugin",
            target=sample_section,
            page=random.choice(organizations).extended_object,  # nosec
        )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="CoursePlugin",
            target=sample_section,
            page=random.choice(courses).extended_object,  # nosec
        )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="OrganizationPlugin",
            target=sample_section,
            page=random.choice(organizations).extended_object,  # nosec
        )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="BlogPostPlugin",
            target=sample_section,
            page=random.choice(blogposts).extended_object,  # nosec
        )
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LinkPlugin",
            target=sample_section,
            name=content["section_sample_button_title"],
            template=content["button_template_name"],
            internal_link=pages_created["home"],
        )
        # Add a licence
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LicencePlugin",
            licence=random.choice(licences),  # nosec
        )
        # Add a simple picture entry
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SimplePicturePlugin",
            picture=logo,
        )
        # Add a plain text
        text = factory.Faker(
            "text", max_nb_chars=random.randint(150, 250), locale=language  # nosec
        ).generate({})
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="PlainTextPlugin",
            body=text,
        )

        # Once content has been added we must publish again the about page
        pages_created["annex__about"].publish(language)

    # Create a sitemap page
    placeholder = pages_created["annex__sitemap"].placeholders.get(slot="maincontent")

    for language in pages_created["annex__sitemap"].get_languages():
        parent_instance = add_plugin(
            language=language, placeholder=placeholder, plugin_type="HTMLSitemapPlugin"
        )
        for name, params in SITEMAP_PAGE_PARAMS.items():
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="HTMLSitemapPagePlugin",
                target=parent_instance,
                root_page=pages_created[name],
                **params,
            )

        # Once content has been added we must publish again the sitemap
        pages_created["annex__sitemap"].publish(language)
Пример #2
0
def create_demo_site():
    """
    Create a simple site tree structure for developpers to work in realistic environment.

    We create multilingual pages, add organizations under the related page and add
    plugins to each page.
    """
    site = Site.objects.get(id=1)

    # Create pages as described in PAGES_INFOS
    pages_created = recursive_page_creation(site, PAGE_INFOS)

    # Create some licences
    licences = LicenceFactory.create_batch(NB_LICENCES)

    # Create organizations under the `Organizations` page
    organizations = OrganizationFactory.create_batch(
        NB_ORGANIZATIONS,
        languages=[l[0] for l in settings.LANGUAGES],
        parent=pages_created["organizations"],
        fill_banner=True,
        fill_description=True,
        fill_logo=True,
        should_publish=True,
        in_navigation=True,
    )

    # Create subjects under the `Subjects` page
    subjects = SubjectFactory.create_batch(
        NB_SUBJECTS,
        languages=[l[0] for l in settings.LANGUAGES],
        parent=pages_created["subjects"],
        fill_banner=True,
        fill_description=True,
        fill_logo=True,
        should_publish=True,
        in_navigation=True,
    )

    # Django parler require a language to be manually set when working out of
    # request/response flow and PersonTitle use 'parler'
    translation.activate(settings.LANGUAGE_CODE)

    # Create persons under the `persons` page
    persons = PersonFactory.create_batch(
        NB_PERSONS,
        languages=[l[0] for l in settings.LANGUAGES],
        parent=pages_created["persons"],
        fill_portrait=True,
        fill_resume=True,
        should_publish=True,
        in_navigation=True,
    )

    # Create courses under the `Course` page with subjects and organizations
    # relations
    for _ in range(NB_COURSES):
        course_organizations = random.sample(
            organizations, NB_COURSES_ORGANIZATION_RELATIONS)
        video_sample = random.choice(VIDEO_SAMPLE_LINKS)

        course = CourseFactory(
            languages=[l[0] for l in settings.LANGUAGES],
            parent=pages_created["courses"],
            organization_main=random.choice(course_organizations),
            fill_licences=[
                ("course_license_content", random.choice(licences)),
                ("course_license_participation", random.choice(licences)),
            ],
            fill_team=random.sample(persons, NB_COURSES_PERSONS_PLUGINS),
            fill_teaser=video_sample,
            fill_cover=video_sample.image,
            fill_texts=[
                "course_syllabus",
                "course_format",
                "course_prerequisites",
                "course_plan",
                # "course_license_content",
                # "course_license_participation",
            ],
            with_organizations=course_organizations,
            with_subjects=random.sample(subjects,
                                        NB_COURSES_SUBJECT_RELATIONS),
            should_publish=True,
            in_navigation=True,
        )
        # Add a random number of course runs to the course
        nb_course_runs = get_number_of_course_runs()
        if nb_course_runs > 0:
            CourseRunFactory.create_batch(nb_course_runs, course=course)
    def test_templates_course_detail_rdfa(self):
        """
        Extract RDFa tags from the HTML markup and check that it is complete as expected.
        """
        # Create organizations
        main_organization = OrganizationFactory(page_title="Main org",
                                                fill_logo=True,
                                                should_publish=True)
        other_organization = OrganizationFactory(page_title="Other org",
                                                 fill_logo=True,
                                                 should_publish=True)

        # Create persons
        author1 = PersonFactory(page_title="François", fill_portrait=True)
        placeholder = author1.extended_object.placeholders.get(slot="bio")
        add_plugin(
            language="en",
            placeholder=placeholder,
            plugin_type="PlainTextPlugin",
            body="La bio de François",
        )
        author2 = PersonFactory(page_title="Jeanne",
                                fill_portrait=True,
                                should_publish=True)

        # Create a course with cover image, team and organizations
        licence_content, licence_participation = LicenceFactory.create_batch(2)
        course = CourseFactory(
            code="abcde",
            effort=[3, "hour"],
            page_title="Very interesting course",
            fill_cover=True,
            fill_organizations=[main_organization, other_organization],
            fill_team=[author1, author2],
            fill_licences=[
                ("course_license_content", licence_content),
                ("course_license_participation", licence_participation),
            ],
        )

        # Add an introduction to the course
        placeholder = course.extended_object.placeholders.get(
            slot="course_introduction")
        add_plugin(
            language="en",
            placeholder=placeholder,
            plugin_type="PlainTextPlugin",
            body="Introduction to interesting course",
        )

        # Create an ongoing open course run that will be published (created before
        # publishing the page)
        now = datetime(2030, 6, 15, tzinfo=timezone.utc)
        CourseRunFactory(
            direct_course=course,
            start=datetime(2030, 6, 30, tzinfo=timezone.utc),
            end=datetime(2030, 8, 1, tzinfo=timezone.utc),
            enrollment_start=datetime(2030, 6, 14, tzinfo=timezone.utc),
            enrollment_end=datetime(2030, 6, 16, tzinfo=timezone.utc),
            languages=["en", "fr"],
        )
        CourseRunFactory(
            direct_course=course,
            start=datetime(2030, 6, 1, tzinfo=timezone.utc),
            end=datetime(2030, 7, 10, tzinfo=timezone.utc),
            enrollment_start=datetime(2030, 6, 13, tzinfo=timezone.utc),
            enrollment_end=datetime(2030, 6, 20, tzinfo=timezone.utc),
            languages=["de"],
        )

        author1.extended_object.publish("en")
        course.extended_object.publish("en")

        url = course.extended_object.get_absolute_url()
        with mock.patch.object(timezone, "now", return_value=now):
            response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        processor = pyRdfa()
        content = str(response.content)
        parser = html5lib.HTMLParser(
            tree=html5lib.treebuilders.getTreeBuilder("dom"))
        dom = parser.parse(io.StringIO(content))
        graph = processor.graph_from_DOM(dom)

        # Retrieve the course top node (body)
        (subject, ) = graph.subjects(
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/Course"),
        )
        self.assertEqual(len(list(graph.triples((subject, None, None)))), 38)

        # Opengraph
        self.assertTrue((
            subject,
            URIRef("http://ogp.me/ns#url"),
            Literal("http://example.com/en/very-interesting-course/"),
        ) in graph)
        self.assertTrue((subject, URIRef("http://ogp.me/ns#site_name"),
                         Literal("example.com")) in graph)
        self.assertTrue((subject, URIRef("http://ogp.me/ns#type"),
                         Literal("website")) in graph)
        self.assertTrue((subject, URIRef("http://ogp.me/ns#locale"),
                         Literal("en")) in graph)
        self.assertTrue((subject, URIRef("http://ogp.me/ns#determiner"),
                         Literal("")) in graph)
        self.assertTrue((
            subject,
            URIRef("http://ogp.me/ns#title"),
            Literal("Very interesting course"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("http://ogp.me/ns#description"),
            Literal("Introduction to interesting course"),
        ) in graph)

        (image_value, ) = graph.objects(subject,
                                        URIRef("http://ogp.me/ns#image"))
        pattern = (
            r"/media/filer_public_thumbnails/filer_public/.*cover\.jpg__"
            r"1200x630_q85_crop_replace_alpha-%23FFFFFF_subject_location")
        self.assertIsNotNone(re.search(pattern, str(image_value)))

        # Schema.org
        # - Course
        self.assertTrue((
            subject,
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/Course"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/name"),
            Literal("Very interesting course"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/description"),
            Literal("Introduction to interesting course"),
        ) in graph)
        self.assertTrue((subject, URIRef("https://schema.org/courseCode"),
                         Literal("ABCDE")) in graph)
        self.assertTrue((subject,
                         URIRef("https://schema.org/isAccessibleForFree"),
                         Literal("true")) in graph)
        self.assertTrue((subject, URIRef("https://schema.org/timeRequired"),
                         Literal("PT3H")) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/stylesheet"),
            URIRef("/static/richie/css/main.css"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/shortcut"),
            URIRef("/static/richie/favicon/favicon.ico"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/icon"),
            URIRef("/static/richie/favicon/favicon.ico"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/icon"),
            URIRef("/static/richie/favicon/favicon-16x16.png"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/icon"),
            URIRef("/static/richie/favicon/favicon-32x32.png"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/apple-touch-icon"),
            URIRef("/static/richie/favicon/apple-touch-icon.png"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/mask-icon"),
            URIRef("/static/richie/favicon/safari-pinned-tab.svg"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/manifest"),
            URIRef("/static/richie/favicon/site.webmanifest"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/noreferrer"),
            URIRef("https://www.facebook.com/example"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/noopener"),
            URIRef("https://www.facebook.com/example"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/alternate"),
            URIRef("http://example.com/en/very-interesting-course/"),
        ) in graph)
        self.assertTrue((
            subject,
            URIRef("https://schema.org/alternate"),
            URIRef("http://example.com/fr/very-interesting-course/"),
        ) in graph)

        (image_value, ) = graph.objects(subject,
                                        URIRef("https://schema.org/image"))
        pattern = (
            r"/media/filer_public_thumbnails/filer_public/.*cover\.jpg__"
            r"300x170_q85_crop_replace_alpha-%23FFFFFF_subject_location")
        self.assertIsNotNone(re.search(pattern, str(image_value)))

        self.assertTrue((subject, URIRef("https://schema.org/license"),
                         URIRef(licence_content.url)) in graph)
        self.assertTrue((
            None,
            URIRef("https://schema.org/license"),
            URIRef(licence_participation.url),
        ) not in graph)
        # - Main organization (Provider)
        self.assertTrue((subject, URIRef("https://schema.org/provider"),
                         URIRef("/en/main-org/")) in graph)
        self.assertTrue((
            URIRef("/en/main-org/"),
            URIRef("https://schema.org/name"),
            Literal("Main org"),
        ) in graph)
        self.assertTrue((
            URIRef("/en/main-org/"),
            URIRef("https://schema.org/url"),
            Literal("http://example.com/en/main-org/"),
        ) in graph)

        (logo_value, ) = graph.objects(URIRef("/en/main-org/"),
                                       URIRef("https://schema.org/logo"))
        pattern = (r"/media/filer_public_thumbnails/filer_public/.*logo.jpg__"
                   r"200x113_q85_replace_alpha-%23FFFFFF_subject_location")
        self.assertIsNotNone(re.search(pattern, str(logo_value)))

        # - Organizations (Contributor)
        contributor_subjects = list(
            graph.objects(subject, URIRef("https://schema.org/contributor")))
        self.assertEqual(len(contributor_subjects), 2)

        self.assertTrue((
            contributor_subjects[0],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/CollegeOrUniversity"),
        ) in graph)
        self.assertTrue((
            contributor_subjects[1],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/CollegeOrUniversity"),
        ) in graph)

        self.assertTrue((
            URIRef("/en/main-org/"),
            URIRef("https://schema.org/name"),
            Literal("Main org"),
        ) in graph)

        self.assertTrue((
            URIRef("/en/other-org/"),
            URIRef("https://schema.org/name"),
            Literal("Other org"),
        ) in graph)

        self.assertTrue((
            URIRef("/en/main-org/"),
            URIRef("https://schema.org/url"),
            Literal("http://example.com/en/main-org/"),
        ) in graph)

        self.assertTrue((
            URIRef("/en/other-org/"),
            URIRef("https://schema.org/url"),
            Literal("http://example.com/en/other-org/"),
        ) in graph)

        pattern = (r"/media/filer_public_thumbnails/filer_public/.*logo.jpg__"
                   r"200x113_q85_replace_alpha-%23FFFFFF_subject_location")
        (logo_value, ) = graph.objects(URIRef("/en/main-org/"),
                                       URIRef("https://schema.org/logo"))
        self.assertIsNotNone(re.search(pattern, str(logo_value)))

        (logo_value, ) = graph.objects(URIRef("/en/other-org/"),
                                       URIRef("https://schema.org/logo"))
        self.assertIsNotNone(re.search(pattern, str(logo_value)))

        # - Team (Person)
        author_subjects = list(
            graph.objects(subject, URIRef("https://schema.org/author")))
        self.assertEqual(len(author_subjects), 2)

        self.assertTrue((
            author_subjects[0],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/Person"),
        ) in graph)
        self.assertTrue((
            author_subjects[1],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/Person"),
        ) in graph)

        for name in ["Fran\\xc3\\xa7ois", "Jeanne"]:
            (author_subject, ) = graph.subjects(
                URIRef("https://schema.org/name"), Literal(name))
            self.assertTrue(author_subject in author_subjects)

        (author_subject, ) = graph.subjects(
            URIRef("https://schema.org/description"),
            Literal("La bio de Fran\\xc3\\xa7ois"),
        )
        self.assertTrue(author_subject in author_subjects)

        for url in [
                "http://example.com/en/francois/",
                "http://example.com/en/jeanne/"
        ]:
            (author_subject, ) = graph.subjects(
                URIRef("https://schema.org/url"), Literal(url))
            self.assertTrue(author_subject in author_subjects)

        pattern = (
            r"/media/filer_public_thumbnails/filer_public/.*portrait.jpg__"
            r"200x200_q85_crop_replace_alpha-%23FFFFFF_subject_location")
        for author_subject in author_subjects:
            (portrait_value, ) = graph.objects(
                author_subject, URIRef("https://schema.org/image"))
            self.assertIsNotNone(re.search(pattern, str(portrait_value)))

        # - Course runs (CourseInstance)
        course_run_subjects = list(
            graph.objects(subject,
                          URIRef("https://schema.org/hasCourseInstance")))
        self.assertEqual(len(course_run_subjects), 2)

        self.assertTrue((
            course_run_subjects[0],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/CourseInstance"),
        ) in graph)
        self.assertTrue((
            course_run_subjects[0],
            URIRef("https://schema.org/courseMode"),
            Literal("online"),
        ) in graph)
        self.assertTrue((
            course_run_subjects[1],
            URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
            URIRef("https://schema.org/CourseInstance"),
        ) in graph)
        self.assertTrue((
            course_run_subjects[1],
            URIRef("https://schema.org/courseMode"),
            Literal("online"),
        ) in graph)

        for start_date in ["2030-06-01", "2030-06-30"]:
            (subject, ) = graph.subjects(
                URIRef("https://schema.org/startDate"), Literal(start_date))
            self.assertTrue(subject in course_run_subjects)

        for end_date in ["2030-07-10", "2030-08-01"]:
            (subject, ) = graph.subjects(URIRef("https://schema.org/endDate"),
                                         Literal(end_date))
            self.assertTrue(subject in course_run_subjects)
Пример #4
0
def create_demo_site():
    """
    Create a simple site tree structure for developpers to work in realistic environment.

    We create multilingual pages, add organizations under the related page and add
    plugins to each page.
    """
    site = Site.objects.get(id=1)

    # Create pages as described in PAGES_INFOS
    pages_created = recursive_page_creation(site, PAGE_INFOS)

    # Create some licences
    licences = LicenceFactory.create_batch(NB_LICENCES)

    # Create organizations under the `Organizations` page
    organizations = OrganizationFactory.create_batch(
        NB_ORGANIZATIONS,
        page_in_navigation=True,
        page_languages=["en", "fr"],
        page_parent=pages_created["organizations"],
        fill_banner=True,
        fill_description=True,
        fill_logo=True,
        should_publish=True,
    )

    # Generate each category tree and return a list of the leaf categories
    levels = list(create_categories(LEVELS_INFO, pages_created["categories"]))
    subjects = list(
        create_categories(SUBJECTS_INFO, pages_created["categories"]))

    title = PersonTitleFactory(translation=None)
    PersonTitleTranslationFactory(master=title,
                                  language_code="en",
                                  title="Doctor",
                                  abbreviation="Dr.")
    PersonTitleTranslationFactory(master=title,
                                  language_code="fr",
                                  title="Docteur",
                                  abbreviation="Dr.")

    # Create persons under the `persons` page
    persons = PersonFactory.create_batch(
        NB_PERSONS,
        page_in_navigation=True,
        page_languages=["en", "fr"],
        page_parent=pages_created["persons"],
        person_title=random.choice([title, None]),
        fill_portrait=True,
        fill_resume=True,
        should_publish=True,
    )

    # Create courses under the `Course` page with categories and organizations
    # relations
    courses = []
    for _ in range(NB_COURSES):
        video_sample = random.choice(VIDEO_SAMPLE_LINKS)

        course = CourseFactory(
            page_in_navigation=True,
            page_languages=["en", "fr"],
            page_parent=pages_created["courses"],
            fill_licences=[
                ("course_license_content", random.choice(licences)),
                ("course_license_participation", random.choice(licences)),
            ],
            fill_team=random.sample(persons, NB_COURSES_PERSONS_PLUGINS),
            fill_teaser=video_sample,
            fill_cover=video_sample.image,
            fill_categories=[
                *random.sample(
                    subjects, random.randint(1, NB_COURSES_SUBJECT_RELATIONS)),
                random.choice(levels),
            ],
            fill_organizations=random.sample(
                organizations, NB_COURSES_ORGANIZATION_RELATIONS),
            fill_texts=[
                "course_syllabus",
                "course_format",
                "course_prerequisites",
                "course_plan",
                # "course_license_content",
                # "course_license_participation",
            ],
            should_publish=True,
        )
        courses.append(course)

        # Add a random number of course runs to the course
        nb_course_runs = get_number_of_course_runs()

        # 1) Make sure we have one course run open for enrollment
        now = timezone.now()
        CourseRunFactory(
            __sequence=nb_course_runs,
            page_in_navigation=False,
            page_parent=course.extended_object,
            start=now + timedelta(days=1),
            enrollment_start=now - timedelta(days=5),
            enrollment_end=now + timedelta(days=5),
            should_publish=True,
        )

        # 2) Add more random course runs
        for i in range(nb_course_runs - 1, 0, -1):
            CourseRunFactory(
                __sequence=i,
                page_in_navigation=False,
                page_languages=["en", "fr"],
                page_parent=course.extended_object,
                should_publish=True,
            )

    # Once everything has been created, use some content to create a homepage
    placeholder = pages_created["home"].placeholders.get(slot="maincontent")

    # - Get a banner image
    banner_file = file_getter("banner")()
    wrapped_banner = File(banner_file, banner_file.name)
    banner = Image.objects.create(file=wrapped_banner)

    # - Get a logo image
    logo_file = file_getter("logo")()
    wrapped_logo = File(logo_file, logo_file.name)
    logo = Image.objects.create(file=wrapped_logo)

    # - Create the home page in each language
    for language, content in HOMEPAGE_CONTENT.items():
        # Add a banner
        add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="LargeBannerPlugin",
            title=content["banner_title"],
            background_image=banner,
            logo=logo,
            logo_alt_text="logo",
            content=content["banner_content"],
            template=content["banner_template"],
        )
        # Add highlighted courses
        courses_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["courses_title"],
            template=content["section_template"],
        )
        for course in random.sample(courses, NB_HOME_HIGHLIGHTED_COURSES):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="CoursePlugin",
                target=courses_section,
                page=course.extended_object,
            )

        # Add highlighted organizations
        organizations_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["organizations_title"],
            template=content["section_template"],
        )
        for organization in random.sample(organizations,
                                          NB_HOME_HIGHLIGHTED_ORGANIZATIONS):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="OrganizationPlugin",
                target=organizations_section,
                page=organization.extended_object,
            )

        # Add highlighted subjects
        subjects_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["subjects_title"],
            template=content["section_template"],
        )
        for subject in random.sample(subjects, NB_HOME_HIGHLIGHTED_SUBJECTS):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="CategoryPlugin",
                target=subjects_section,
                page=subject.extended_object,
            )

        # Add highlighted persons
        persons_section = add_plugin(
            language=language,
            placeholder=placeholder,
            plugin_type="SectionPlugin",
            title=content["persons_title"],
            template=content["section_template"],
        )
        for person in random.sample(persons, NB_HOME_HIGHLIGHTED_PERSONS):
            add_plugin(
                language=language,
                placeholder=placeholder,
                plugin_type="PersonPlugin",
                target=persons_section,
                page=person.extended_object,
            )

        # Once content has been added we must publish again homepage in every
        # edited Languages
        pages_created["home"].publish("en")
        pages_created["home"].publish("fr")
Пример #5
0
    def test_indexers_courses_get_es_documents_from_models(
            self, _mock_picture):
        """
        Happy path: the data is retrieved from the models properly formatted
        """
        # Create a course with a page in both english and french
        published_categories = [
            CategoryFactory(
                fill_icon=True,
                page_title={
                    "en": "Title cat 1",
                    "fr": "Titre cat 1"
                },
                should_publish=True,
            ),
            CategoryFactory(
                fill_icon=True,
                page_title={
                    "en": "Title cat 2",
                    "fr": "Titre cat 2"
                },
                should_publish=True,
            ),
        ]
        draft_category = CategoryFactory(fill_icon=True)

        main_organization = OrganizationFactory(
            page_title={
                "en": "english main organization title",
                "fr": "titre organisation principale français",
            },
            should_publish=True,
        )
        other_draft_organization = OrganizationFactory(
            page_title={
                "en": "english other organization title",
                "fr": "titre autre organisation français",
            })
        other_published_organization = OrganizationFactory(
            page_title={
                "en": "english other organization title",
                "fr": "titre autre organisation français",
            },
            should_publish=True,
        )

        person1 = PersonFactory(
            page_title={
                "en": "Eugène Delacroix",
                "fr": "Eugène Delacroix"
            },
            should_publish=True,
        )
        person2 = PersonFactory(
            page_title={
                "en": "Comte de Saint-Germain",
                "fr": "Earl of Saint-Germain"
            },
            should_publish=True,
        )
        person_draft = PersonFactory(page_title={
            "en": "Jules de Polignac",
            "fr": "Jules de Polignac"
        })

        licence1, licence2, licence3, _licence4 = LicenceFactory.create_batch(
            4)
        # Keep a licence unused to check that it is not returned. Link also licences to the
        # "student content licence" placeholder to check they are ignored
        licences_by_placeholders = [
            ("course_license_content", licence1),
            ("course_license_content", licence2),
            ("course_license_participation", licence2),
            ("course_license_participation", licence3),
        ]

        course = CourseFactory(
            duration=[3, WEEK],
            effort=[2, HOUR],
            fill_categories=published_categories + [draft_category],
            fill_cover=True,
            fill_icons=published_categories + [draft_category],
            fill_licences=licences_by_placeholders,
            fill_organizations=[
                main_organization,
                other_draft_organization,
                other_published_organization,
            ],
            fill_team=[person1, person_draft, person2],
            page_title={
                "en": "an english course title",
                "fr": "un titre cours français",
            },
        )
        CourseRunFactory.create_batch(2, direct_course=course)
        course.extended_object.publish("en")
        course.extended_object.publish("fr")
        course.refresh_from_db()

        # Add a description in several languages
        placeholder = course.public_extension.extended_object.placeholders.get(
            slot="course_description")
        plugin_params = {
            "placeholder": placeholder,
            "plugin_type": "CKEditorPlugin"
        }
        add_plugin(body="english description line 1.",
                   language="en",
                   **plugin_params)
        add_plugin(body="english description line 2.",
                   language="en",
                   **plugin_params)
        add_plugin(body="a propos français ligne 1.",
                   language="fr",
                   **plugin_params)
        add_plugin(body="a propos français ligne 2.",
                   language="fr",
                   **plugin_params)

        # Add an introduction in several languages
        placeholder = course.public_extension.extended_object.placeholders.get(
            slot="course_introduction")
        plugin_params = {
            "placeholder": placeholder,
            "plugin_type": "PlainTextPlugin"
        }
        add_plugin(body="english introduction.",
                   language="en",
                   **plugin_params)
        add_plugin(body="introduction française.",
                   language="fr",
                   **plugin_params)

        # The results were properly formatted and passed to the consumer
        expected_course = {
            "_id":
            course.get_es_id(),
            "_index":
            "some_index",
            "_op_type":
            "some_action",
            "absolute_url": {
                "en": "/en/an-english-course-title/",
                "fr": "/fr/un-titre-cours-francais/",
            },
            "categories": [
                published_categories[0].get_es_id(),
                published_categories[1].get_es_id(),
            ],
            "categories_names": {
                "en": ["Title cat 1", "Title cat 2"],
                "fr": ["Titre cat 1", "Titre cat 2"],
            },
            "code":
            course.code,
            "complete": {
                "en": [
                    "an english course title",
                    "english course title",
                    "course title",
                    "title",
                ],
                "fr": [
                    "un titre cours français",
                    "titre cours français",
                    "cours français",
                    "français",
                ],
            },
            "course_runs": [{
                "start":
                course_run.public_course_run.start,
                "end":
                course_run.public_course_run.end,
                "enrollment_start":
                course_run.public_course_run.enrollment_start,
                "enrollment_end":
                course_run.public_course_run.enrollment_end,
                "languages":
                course_run.public_course_run.languages,
            } for course_run in course.course_runs.order_by("-end")],
            "cover_image": {
                "en": {
                    "info": "picture info"
                },
                "fr": {
                    "info": "picture info"
                },
            },
            "description": {
                "en":
                "english description line 1. english description line 2.",
                "fr": "a propos français ligne 1. a propos français ligne 2.",
            },
            "duration": {
                "en": "3 weeks",
                "fr": "3 semaines"
            },
            "effort": {
                "en": "2 hours",
                "fr": "2 heures"
            },
            "icon": {
                "en": {
                    "color": published_categories[0].color,
                    "info": "picture info",
                    "title": "Title cat 1",
                },
                "fr": {
                    "color": published_categories[0].color,
                    "info": "picture info",
                    "title": "Titre cat 1",
                },
            },
            "introduction": {
                "en": "english introduction.",
                "fr": "introduction française.",
            },
            "is_new":
            False,
            "is_listed":
            True,
            "licences": [licence1.id, licence2.id],
            "organization_highlighted": {
                "en": "english main organization title",
                "fr": "titre organisation principale français",
            },
            "organization_highlighted_cover_image": {},
            "organizations": [
                main_organization.get_es_id(),
                other_published_organization.get_es_id(),
            ],
            "organizations_names": {
                "en": [
                    "english main organization title",
                    "english other organization title",
                ],
                "fr": [
                    "titre organisation principale français",
                    "titre autre organisation français",
                ],
            },
            "persons": [
                person1.get_es_id(),
                person2.get_es_id(),
            ],
            "persons_names": {
                "en": ["Eugène Delacroix", "Comte de Saint-Germain"],
                "fr": ["Eugène Delacroix", "Earl of Saint-Germain"],
            },
            "pace":
            40,
            "title": {
                "fr": "un titre cours français",
                "en": "an english course title"
            },
        }
        indexed_courses = list(
            CoursesIndexer.get_es_documents(index="some_index",
                                            action="some_action"))
        self.assertEqual(len(indexed_courses), 1)
        self.assertEqual(indexed_courses[0], expected_course)