def test_helpers_simplepicture_get_picture_info_no_picture(self): """ The `get_picture_info` method should not fail and raise an error if it encounters a picture without an image. """ simple_picture = PictureFactory(picture=None) info = get_picture_info(simple_picture, "my-preset") self.assertEqual(info, None)
def get_es_document_for_organization(cls, organization, index=None, action="index"): """Build an Elasticsearch document from the category instance.""" index = index or cls.index_name # Get published titles titles = { t.language: t.title for t in Title.objects.filter(page=organization.extended_object, published=True) } # Prepare logo images logo_images = {} for logo in Picture.objects.filter( cmsplugin_ptr__placeholder__page=organization.extended_object, cmsplugin_ptr__placeholder__slot="logo", ): language = logo.cmsplugin_ptr.language with translation.override(language): logo_images[language] = get_picture_info(logo, "logo") # Get description texts description = defaultdict(list) for simple_text in SimpleText.objects.filter( cmsplugin_ptr__placeholder__page=organization.extended_object, cmsplugin_ptr__placeholder__slot="description", ): description[simple_text.cmsplugin_ptr.language].append( simple_text.body) return { "_id": organization.get_es_id(), "_index": index, "_op_type": action, "_type": cls.document_type, "absolute_url": { language: organization.extended_object.get_absolute_url(language) for language in titles.keys() }, "complete": { language: slice_string_for_completion(title) for language, title in titles.items() }, "logo": logo_images, "description": {language: " ".join(st) for language, st in description.items()}, "title": titles, }
def get_logo_images(cls, organization): """ Prepare logo images for an organization. """ logo_images = {} for logo in Picture.objects.filter( cmsplugin_ptr__placeholder__page=organization.extended_object, cmsplugin_ptr__placeholder__slot="logo", ): language = logo.cmsplugin_ptr.language with translation.override(language): logo_images[language] = get_picture_info(logo, "logo") return logo_images
def get_es_document_for_person(cls, person, index=None, action="index"): """Build an Elasticsearch document from the person instance.""" index = index or cls.index_name # Get published titles titles = { t.language: t.title for t in Title.objects.filter(page=person.extended_object, published=True) } # Prepare portrait images portrait_images = {} for portrait in Picture.objects.filter( cmsplugin_ptr__placeholder__page=person.extended_object, cmsplugin_ptr__placeholder__slot="portrait", ): language = portrait.cmsplugin_ptr.language with translation.override(language): portrait_images[language] = get_picture_info( portrait, "portrait") # Get bio texts bio = defaultdict(list) for simple_text in SimpleText.objects.filter( cmsplugin_ptr__placeholder__page=person.extended_object, cmsplugin_ptr__placeholder__slot="bio", ): bio[simple_text.cmsplugin_ptr.language].append(simple_text.body) return { "_id": str(person.extended_object_id), "_index": index, "_op_type": action, "_type": cls.document_type, "absolute_url": { language: person.extended_object.get_absolute_url(language) for language in titles.keys() }, "bio": {l: " ".join(st) for l, st in bio.items()}, "complete": { language: slice_string_for_completion(title) for language, title in titles.items() }, "portrait": portrait_images, "title": titles, }
def test_helpers_simplepicture_get_picture_info_minimal( self, mock_thumbnail): """srcset and sizes are optional attributes in settings.""" simple_picture = PictureFactory() info = get_picture_info(simple_picture, "my-preset") self.assertEqual(info, { "sizes": None, "src": "/dummy-url", "srcset": None }) self.assertEqual(mock_thumbnail.call_count, 1) location = simple_picture.picture.subject_location self.assertEqual( mock_thumbnail.call_args_list, [mock.call({ "size": (500, 500), "subject_location": location })], )
def test_helpers_simplepicture_get_picture_info_success( self, mock_thumbnail, *_): """ The `get_picture_info` method should compute and return thumbnails urls and other attributes. """ simple_picture = PictureFactory() info = get_picture_info(simple_picture, "my-preset") self.assertEqual( info, { "sizes": "100vw", "src": "/dummy-url", "srcset": "/dummy-url 1000w, /dummy-url 2000w", }, ) self.assertEqual(mock_thumbnail.call_count, 3) location = simple_picture.picture.subject_location self.assertEqual( mock_thumbnail.call_args_list, [ mock.call({ "size": (500, 500), "crop": "smart", "subject_location": location }), mock.call({ "crop": "smart", "size": (1000, 1000), "subject_location": location, }), mock.call({ "crop": "smart", "size": (2000, 2000), "subject_location": location, }), ], )
def get_es_document_for_course(cls, course, index=None, action="index"): """ Build an Elasticsearch document from the course instance. """ index = index or cls.index_name # Prepare published titles titles = { t.language: t.title for t in Title.objects.filter(page=course.extended_object, published=True) } # Prepare cover images cover_images = {} for cover in Picture.objects.filter( cmsplugin_ptr__placeholder__page=course.extended_object, cmsplugin_ptr__placeholder__slot="course_cover", ): language = cover.cmsplugin_ptr.language with translation.override(language): picture_info = get_picture_info(cover, "cover") if picture_info: cover_images[language] = picture_info # Prepare the related category icon icon_images = {} for plugin_model in CategoryPluginModel.objects.filter( cmsplugin_ptr__placeholder__page=course.extended_object_id, cmsplugin_ptr__placeholder__slot="course_icons", cmsplugin_ptr__position=0, ): language = plugin_model.language for icon in Picture.objects.filter( cmsplugin_ptr__language=language, cmsplugin_ptr__placeholder__page=plugin_model.page_id, cmsplugin_ptr__placeholder__slot="icon", cmsplugin_ptr__position=0, ): with translation.override(language): picture_info = get_picture_info(icon, "icon") or {} icon_images[language] = { **picture_info, "color": plugin_model.page.category.color, "title": plugin_model.page.get_title(), } # Prepare description texts descriptions = defaultdict(list) for simple_text in SimpleText.objects.filter( cmsplugin_ptr__placeholder__page=course.extended_object, cmsplugin_ptr__placeholder__slot="course_description", ): descriptions[simple_text.cmsplugin_ptr.language].append(simple_text.body) # Prepare localized duration texts duration = {} for language, _ in settings.LANGUAGES: with translation.override(language): duration[language] = course.get_duration_display() # Prepare localized effort texts effort = {} for language, _ in settings.LANGUAGES: with translation.override(language): effort[language] = course.get_effort_display() # Prepare categories, making sure we get title information for categories # in the same query category_pages = ( course.get_root_to_leaf_category_pages() .select_related("node") .prefetch_related( Prefetch( "title_set", to_attr="published_titles", queryset=Title.objects.filter(published=True), ) ) .only("node", "pk") .distinct() ) # Prepare organizations, making sure we get title information for organizations # in the same query organizations = ( course.get_organizations() .prefetch_related( Prefetch( "extended_object__title_set", to_attr="published_titles", queryset=Title.objects.filter(published=True), ) ) .only("extended_object__node") .distinct() ) organization_main = course.get_main_organization() organization_highlighted = ( organizations.get(id=organization_main.id) if organization_main else None ) # Prepare persons, making sure we get title information for persons # in the same query persons = ( course.get_persons() .prefetch_related( Prefetch( "extended_object__title_set", to_attr="published_titles", queryset=Title.objects.filter(published=True), ) ) .distinct() ) # Prepare course runs # Ordering them by their `end` date is important to optimize sorting and other # computations that require looping on the course runs # Course runs with no start date or no start of enrollment date are ignored as # they are still to be scheduled. course_runs = [ { "start": cr["start"], "end": cr["end"] or MAX_DATE, "enrollment_start": cr["enrollment_start"], "enrollment_end": cr["enrollment_end"] or cr["end"] or MAX_DATE, "languages": cr["languages"], } for cr in course.get_course_runs() .filter(start__isnull=False, enrollment_start__isnull=False) .order_by("-end") .values("start", "end", "enrollment_start", "enrollment_end", "languages") ] return { "_id": str(course.extended_object_id), "_index": index, "_op_type": action, "_type": cls.document_type, "absolute_url": { lang: course.extended_object.get_absolute_url(lang) for lang, _ in settings.LANGUAGES }, "categories": [page.category.get_es_id() for page in category_pages], # Index the names of categories to surface them in full text searches "categories_names": reduce( lambda acc, title: { **acc, title.language: acc[title.language] + [title.title] if acc.get(title.language) else [title.title], }, [title for page in category_pages for title in page.published_titles], {}, ), "complete": { language: slice_string_for_completion(title) for language, title in titles.items() } if course.is_listed else None, "course_runs": course_runs, "cover_image": cover_images, "description": { language: " ".join(st) for language, st in descriptions.items() }, "duration": duration, "effort": effort, "icon": icon_images, "is_new": len(course_runs) == 1, "is_listed": course.is_listed, # Pick the highlighted organization from the organizations QuerySet to benefit from # the prefetch of related title sets "organization_highlighted": { title.language: title.title for title in organization_highlighted.extended_object.published_titles } if organization_highlighted else None, "organizations": [ organization.get_es_id() for organization in organizations ], # Index the names of organizations to surface them in full text searches "organizations_names": reduce( lambda acc, title: { **acc, title.language: acc[title.language] + [title.title] if acc.get(title.language) else [title.title], }, [ title for organization in organizations for title in organization.extended_object.published_titles ], {}, ), "persons": [ str(person.public_extension.extended_object_id) for person in persons ], "persons_names": reduce( lambda acc, title: { **acc, title.language: acc[title.language] + [title.title] if acc.get(title.language) else [title.title], }, [ title for person in persons for title in person.extended_object.published_titles ], {}, ), "title": titles, }
def get_es_document_for_category(cls, category, index=None, action="index"): """Build an Elasticsearch document from the category instance.""" index = index or cls.index_name # Prepare published titles titles = { t.language: t.title for t in Title.objects.filter(page=category.extended_object, published=True) } # Prepare logo images logo_images = {} for logo in Picture.objects.filter( cmsplugin_ptr__placeholder__page=category.extended_object, cmsplugin_ptr__placeholder__slot="logo", ): language = logo.cmsplugin_ptr.language with translation.override(language): logo_images[language] = get_picture_info(logo, "logo") # Prepare icon images icon_images = {} for icon in Picture.objects.filter( cmsplugin_ptr__placeholder__page=category.extended_object, cmsplugin_ptr__placeholder__slot="icon", ): language = icon.cmsplugin_ptr.language with translation.override(language): icon_images[language] = get_picture_info(icon, "icon") # Prepare description texts description = defaultdict(list) for simple_text in SimpleText.objects.filter( cmsplugin_ptr__placeholder__page=category.extended_object, cmsplugin_ptr__placeholder__slot="description", ): description[simple_text.cmsplugin_ptr.language].append(simple_text.body) # Shorcut to the category's page node node = category.extended_object.node # Find the meta category the current category falls under try: kind = category.get_meta_category().extended_object.reverse_id except Category.DoesNotExist: # Meta categories do not have a meta category themselves kind = None return { "_id": cls.get_es_id(category.extended_object), "_index": index, "_op_type": action, "_type": cls.document_type, "absolute_url": { language: category.extended_object.get_absolute_url(language) for language in titles.keys() }, "complete": { language: slice_string_for_completion(title) for language, title in titles.items() }, "description": {l: " ".join(st) for l, st in description.items()}, "icon": icon_images, "is_meta": bool( node.parent is None or node.parent.cms_pages.filter(category__isnull=True).exists() ), "kind": kind, "logo": logo_images, "nb_children": node.numchild, "path": node.path, "title": titles, }