Add extra handling to sorting with recommended and relevance

This commit is contained in:
Andrew Williamson 2019-05-27 16:58:01 +01:00
Родитель 1ed7d2d34d
Коммит dcfff013a3
3 изменённых файлов: 37 добавлений и 8 удалений

Просмотреть файл

@ -81,7 +81,10 @@ This endpoint allows you to search through public add-ons.
rating Bayesian rating, descending.
recommended Recommended add-ons above non-recommend add-ons. Only
available combined with another sort - ignored on its own.
relevance Search query relevance, descending.
Also ignored if combined with relevance as it already takes
into account recommended status.
relevance Search query relevance, descending. Ignored without a
query.
updated Last updated date, descending.
users Average number of daily users, descending.
============== ==========================================================

Просмотреть файл

@ -859,7 +859,7 @@ class SortingFilter(BaseFilterBackend):
def filter_queryset(self, request, qs, view):
search_query_param = request.GET.get('q')
sort_param = request.GET.get('sort')
order_by = None
split_sort_params = None
if sort_param is not None:
split_sort_params = sort_param.split(',')
@ -891,11 +891,21 @@ class SortingFilter(BaseFilterBackend):
'when the "featured" or "recommended" parameter is '
'also present, and the "q" parameter absent.')
# Having just recommended sort doesn't make any sense, so ignore it
if sort_param == 'recommended':
sort_param = None
# Sorting by relevance only makes sense with a query string
if not search_query_param and 'relevance' in split_sort_params:
split_sort_params = [
param for param in split_sort_params if not 'relevance']
if sort_param is None:
# Having just recommended sort doesn't make any sense, so ignore it
if split_sort_params == ['recommended']:
split_sort_params = None
# relevance already takes into account recommended so ignore it too
elif ('recommended' in split_sort_params and
'relevance' in split_sort_params):
split_sort_params = [
param for param in split_sort_params if not 'recommended']
if not split_sort_params:
# The default sort depends on the presence of a query: we sort by
# relevance if we have a query, otherwise by recommended,downloads.
recommended_waffle_on = switch_is_active(

Просмотреть файл

@ -401,9 +401,12 @@ class TestSortingFilter(FilterTestsBase):
SORTING_PARAMS.pop('random') # Tested separately below.
SORTING_PARAMS.pop('recommended') # Tested separately below.
for param in SORTING_PARAMS:
for param, es in SORTING_PARAMS.items():
qs = self._filter(data={'sort': param})
assert qs['sort'] == [self._reformat_order(SORTING_PARAMS[param])]
if param == 'relevance':
# relevance without q is ignored so default downloads is used
es = SORTING_PARAMS['downloads']
assert qs['sort'] == [self._reformat_order(es)]
# Having a search query does not change anything, the requested sort
# takes precedence.
for param in SORTING_PARAMS:
@ -496,6 +499,19 @@ class TestSortingFilter(FilterTestsBase):
self._reformat_order('-is_recommended'),
self._reformat_order('-average_daily_users')]
@override_switch('api-recommendations-priority', active=True)
def test_sort_recommended_and_relevance(self):
# with a q, recommended with relevance sort, recommended is ignored.
qs = self._filter(
data={'q': 'something', 'sort': 'recommended,relevance'})
assert qs['sort'] == [self._reformat_order('_score')]
# except if you don't specify a query, then it falls back to default
qs = self._filter(data={'sort': 'recommended,relevance'})
assert qs['sort'] == [
self._reformat_order('-is_recommended'),
self._reformat_order('-average_daily_users')]
class TestSearchParameterFilter(FilterTestsBase):
filter_classes = [SearchParameterFilter]