def test_get_sorting_option(self): """Test get_sorting_option method""" self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_NR_VIEWS[0] ), LoreSortingFields.SORT_BY_NR_VIEWS ) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_NR_ATTEMPTS[0] ), LoreSortingFields.SORT_BY_NR_ATTEMPTS ) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_AVG_GRADE[0] ), LoreSortingFields.SORT_BY_AVG_GRADE ) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_TITLE[0] ), LoreSortingFields.SORT_BY_TITLE ) self.assertEqual( LoreSortingFields.get_sorting_option('foo_field'), LoreSortingFields.SORT_BY_NR_VIEWS )
def repository_view(request, repo_slug): """ View for repository page. """ try: repo = get_repo(repo_slug, request.user.id) except NotFound: raise Http404 except LorePermissionDenied: raise PermissionDenied exports = request.session.get( 'learning_resource_exports', {}).get(repo.slug, []) sortby = dict(request.GET.copy()).get('sortby', []) if (len(sortby) > 0 and sortby[0] in LoreSortingFields.all_sorting_fields()): sortby_field = sortby[0] else: # default value sortby_field = LoreSortingFields.DEFAULT_SORTING_FIELD sorting_options = { "current": LoreSortingFields.get_sorting_option( sortby_field), "all": LoreSortingFields.all_sorting_options_but( sortby_field) } try: page_size = int(request.GET.get(LorePagination.page_size_query_param)) except (ValueError, KeyError, TypeError): page_size = LorePagination.page_size if page_size <= 0: page_size = LorePagination.page_size elif page_size > LorePagination.max_page_size: page_size = LorePagination.max_page_size context = { "repo": repo, "perms_on_cur_repo": get_perms(request.user, repo), "sorting_options_json": json.dumps(sorting_options), "exports_json": json.dumps(exports), "page_size_json": json.dumps(page_size) } return render( request, "repository.html", context )
def test_all_sorting_options_but(self): """Test all_sorting_options_but method""" self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_NR_VIEWS[0] ), [ LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ] ) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_NR_ATTEMPTS[0] ), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ] ) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_AVG_GRADE[0] ), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_TITLE, ] ) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_TITLE[0] ), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, ] ) self.assertEqual( LoreSortingFields.all_sorting_options_but('foo_field'), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ] )
def test_listing_with_sorting(self): """ Hit the listing with sorting and test that the current sorting changes in the interface. The actual sorting of results is tested in search.tests.test_indexing """ url = self.repository_url + "?sortby={0}" base_sorting_str = ('<button type="button" ' 'class="btn btn-default">{0}</button>') # test no sort type body = self.assert_status_code( self.repository_url, HTTP_OK, return_body=True ) self.assertIn( base_sorting_str.format( LoreSortingFields.get_sorting_option( LoreSortingFields.DEFAULT_SORTING_FIELD )[1] ), body ) # test all the allowed sort types for sort_option in LoreSortingFields.all_sorting_options(): sort_url = url.format(sort_option[0]) body = self.assert_status_code( sort_url, HTTP_OK, return_body=True ) self.assertIn( base_sorting_str.format(sort_option[1]), body ) # test sorting by not allowed sort type url_not_allowed_sort_type = url.format('foo_field') body = self.assert_status_code( url_not_allowed_sort_type, HTTP_OK, return_body=True ) self.assertIn( base_sorting_str.format( LoreSortingFields.get_sorting_option( LoreSortingFields.DEFAULT_SORTING_FIELD )[1] ), body )
def test_all_sorting_fields(self): """Test all_sorting_fields method""" self.assertEqual(LoreSortingFields.all_sorting_fields(), [ LoreSortingFields.SORT_BY_NR_VIEWS[0], LoreSortingFields.SORT_BY_NR_ATTEMPTS[0], LoreSortingFields.SORT_BY_AVG_GRADE[0], LoreSortingFields.SORT_BY_TITLE[0], ])
def test_sorting_options(self): """ Test presence of sorting options. """ sortby = "nr_views" resp = self.client.get("/repositories/{slug}/?sortby={sortby}".format( slug=self.repo.slug, sortby=sortby)) self.assertEqual( json.loads(resp.context["sorting_options_json"]), { "current": list(LoreSortingFields.get_sorting_option(sortby)), "all": [ list(x) for x in LoreSortingFields.all_sorting_options_but(sortby) ] })
def test_all_sorting_options(self): """Test all_sorting_options method""" self.assertEqual(LoreSortingFields.all_sorting_options(), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ])
def repository_view(request, repo_slug): """ View for repository page. """ try: repo = get_repo(repo_slug, request.user.id) except NotFound: raise Http404 except LorePermissionDenied: raise PermissionDenied exports = request.session.get('learning_resource_exports', {}).get(repo.slug, []) sortby = dict(request.GET.copy()).get('sortby', []) if (len(sortby) > 0 and sortby[0] in LoreSortingFields.all_sorting_fields()): sortby_field = sortby[0] else: # default value sortby_field = LoreSortingFields.DEFAULT_SORTING_FIELD sorting_options = { "current": LoreSortingFields.get_sorting_option(sortby_field), "all": LoreSortingFields.all_sorting_options_but(sortby_field) } try: page_size = int(request.GET.get(LorePagination.page_size_query_param)) except (ValueError, KeyError, TypeError): page_size = LorePagination.page_size if page_size <= 0: page_size = LorePagination.page_size elif page_size > LorePagination.max_page_size: page_size = LorePagination.max_page_size context = { "repo": repo, "perms_on_cur_repo": get_perms(request.user, repo), "sorting_options_json": json.dumps(sorting_options), "exports_json": json.dumps(exports), "page_size_json": json.dumps(page_size) } return render(request, "repository.html", context)
def construct_queryset(repo_slug, query='', selected_facets=None, sortby=''): """ Create a SearchQuerySet given search parameters. Args: repo_slug (learningresources.models.Repository): Slug for repository being searched. query (unicode): If present, search phrase to use in queryset. selected_facets (list or None): If present, a list of facets to narrow the search with. sortby (unicode): If present, order by this sorting option. Returns: search.utils/SearchResults: The search results. """ if selected_facets is None: selected_facets = [] kwargs = {} if query != "": kwargs["content"] = query if sortby == "": sortby = LoreSortingFields.DEFAULT_SORTING_FIELD # default values in case of weird sorting options sortby, _, order_direction = LoreSortingFields.get_sorting_option( sortby) sortby = "{0}{1}".format(order_direction, sortby) # Do a parallel query using elasticsearch-dsl. if query not in ("", None): tokens = query else: tokens = None terms = {} for facet in selected_facets: key, value = facet.split(":") # Haystack queries for blanks by putting the key last, as the value, # and setting the key to "_missing_." Fix this for elasticsearch-dsl. if key == '_missing_': key, value = value, None if key.endswith("_exact"): key = key[:-len("_exact")] terms[key] = value # This is sneakily being returned instead of the # Haystack queryset created above. results = search_index( tokens=tokens, repo_slug=repo_slug, sort_by=sortby, terms=terms, ) return results
def construct_queryset(repo_slug, query='', selected_facets=None, sortby=''): """ Create a SearchQuerySet given search parameters. Args: repo_slug (learningresources.models.Repository): Slug for repository being searched. query (unicode): If present, search phrase to use in queryset. selected_facets (list or None): If present, a list of facets to narrow the search with. sortby (unicode): If present, order by this sorting option. Returns: search.utils/SearchResults: The search results. """ if selected_facets is None: selected_facets = [] kwargs = {} if query != "": kwargs["content"] = query if sortby == "": sortby = LoreSortingFields.DEFAULT_SORTING_FIELD # default values in case of weird sorting options sortby, _, order_direction = LoreSortingFields.get_sorting_option(sortby) sortby = "{0}{1}".format(order_direction, sortby) # Do a parallel query using elasticsearch-dsl. if query not in ("", None): tokens = query else: tokens = None terms = {} for facet in selected_facets: key, value = facet.split(":") # Haystack queries for blanks by putting the key last, as the value, # and setting the key to "_missing_." Fix this for elasticsearch-dsl. if key == '_missing_': key, value = value, None if key.endswith("_exact"): key = key[:-len("_exact")] terms[key] = value # This is sneakily being returned instead of the # Haystack queryset created above. results = search_index( tokens=tokens, repo_slug=repo_slug, sort_by=sortby, terms=terms, ) return results
def extra_context(self): """Add to the context.""" context = super(RepositoryView, self).extra_context() params = dict(self.request.GET.copy()) qs_prefix = "?" # Chop out page number so we don't end up with # something like ?page=2&page=3&page=4. if "page" in params: params.pop("page") # for the same reason I remove the sorting if "sortby" in params: params.pop("sortby") if len(params) > 0: qs_prefix = [] for key in params.keys(): qs_prefix.append( "&".join([ "{0}={1}".format(key, val) for val in params[key] ]) ) qs_prefix = "?{0}&".format("&".join(qs_prefix)) show_export_button = LearningResource.objects.filter( course__repository__id=self.repo.id ).exists() context.update({ "repo": self.repo, "perms_on_cur_repo": get_perms(self.request.user, self.repo), "vocabularies": get_vocabularies(context["facets"]), "qs_prefix": qs_prefix, "sorting_options": { "current": LoreSortingFields.get_sorting_option( self.sortby), "all": LoreSortingFields.all_sorting_options_but( self.sortby) }, "exports": self.request.session.get( 'learning_resource_exports', {}).get(self.repo.slug, []), "show_export_button": show_export_button }) return context
def test_get_sorting_option(self): """Test get_sorting_option method""" self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_NR_VIEWS[0]), LoreSortingFields.SORT_BY_NR_VIEWS) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_NR_ATTEMPTS[0]), LoreSortingFields.SORT_BY_NR_ATTEMPTS) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_AVG_GRADE[0]), LoreSortingFields.SORT_BY_AVG_GRADE) self.assertEqual( LoreSortingFields.get_sorting_option( LoreSortingFields.SORT_BY_TITLE[0]), LoreSortingFields.SORT_BY_TITLE) self.assertEqual(LoreSortingFields.get_sorting_option('foo_field'), LoreSortingFields.SORT_BY_NR_VIEWS)
def test_all_sorting_fields(self): """Test all_sorting_fields method""" self.assertEqual( LoreSortingFields.all_sorting_fields(), [ LoreSortingFields.SORT_BY_NR_VIEWS[0], LoreSortingFields.SORT_BY_NR_ATTEMPTS[0], LoreSortingFields.SORT_BY_AVG_GRADE[0], LoreSortingFields.SORT_BY_TITLE[0], ] )
def test_all_sorting_options(self): """Test all_sorting_options method""" self.assertEqual( LoreSortingFields.all_sorting_options(), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ] )
def test_sorting_options(self): """ Test presence of sorting options. """ sortby = "nr_views" resp = self.client.get( "/repositories/{slug}/?sortby={sortby}".format( slug=self.repo.slug, sortby=sortby ) ) self.assertEqual( json.loads(resp.context["sorting_options_json"]), { "current": list(LoreSortingFields.get_sorting_option(sortby)), "all": [list(x) for x in LoreSortingFields.all_sorting_options_but(sortby)] } )
def test_listing_with_sorting(self): """ Hit the listing with sorting and test that the current sorting changes in the interface. The actual sorting of results is tested in search.tests.test_indexing """ url = self.repository_url + "?sortby={0}" def get_sorting_options(resp): """Helper function to decode JSON sorting options.""" return json.loads(resp.context['sorting_options_json']) # test no sort type resp = self.client.get(self.repository_url, follow=True) self.assertEqual(resp.status_code, HTTP_OK) self.assertEqual( get_sorting_options(resp)['current'], list(LoreSortingFields.get_sorting_option( LoreSortingFields.DEFAULT_SORTING_FIELD )) ) # test all the allowed sort types for sort_option in LoreSortingFields.all_sorting_options(): sort_url = url.format(sort_option[0]) resp = self.client.get(sort_url, follow=True) self.assertEqual(resp.status_code, HTTP_OK) self.assertEqual( get_sorting_options(resp)['current'], list(sort_option) ) # test sorting by not allowed sort type url_not_allowed_sort_type = url.format('foo_field') resp = self.client.get(url_not_allowed_sort_type, follow=True) self.assertEqual(resp.status_code, HTTP_OK) self.assertEqual( get_sorting_options(resp)['current'], list(LoreSortingFields.get_sorting_option( LoreSortingFields.DEFAULT_SORTING_FIELD )) )
def test_all_sorting_options_but(self): """Test all_sorting_options_but method""" self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_NR_VIEWS[0]), [ LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ]) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_NR_ATTEMPTS[0]), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ]) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_AVG_GRADE[0]), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_TITLE, ]) self.assertEqual( LoreSortingFields.all_sorting_options_but( LoreSortingFields.SORT_BY_TITLE[0]), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, ]) self.assertEqual( LoreSortingFields.all_sorting_options_but('foo_field'), [ LoreSortingFields.SORT_BY_NR_VIEWS, LoreSortingFields.SORT_BY_NR_ATTEMPTS, LoreSortingFields.SORT_BY_AVG_GRADE, LoreSortingFields.SORT_BY_TITLE, ])
def __call__(self, request, repo_slug): # Get arguments from the URL # It's a subclass of an external class, so we don't have # repo_slug in __init__. # pylint: disable=attribute-defined-outside-init try: self.repo = get_repo(repo_slug, request.user.id) except NotFound: raise Http404() except LorePermissionDenied: raise PermissionDenied('unauthorized') # get sorting from params if it's there sortby = dict(request.GET.copy()).get('sortby', []) if (len(sortby) > 0 and sortby[0] in LoreSortingFields.all_sorting_fields()): self.sortby = sortby[0] else: # default value self.sortby = LoreSortingFields.DEFAULT_SORTING_FIELD return super(RepositoryView, self).__call__(request)