Commit 09c0c280 by Dennis Jen Committed by Daniel Friedman

updated sort params

parent 7278f1c5
...@@ -256,25 +256,28 @@ class RosterEntry(DocType): ...@@ -256,25 +256,28 @@ class RosterEntry(DocType):
cohort=None, cohort=None,
enrollment_mode=None, enrollment_mode=None,
text_search=None, text_search=None,
order_by_fields=None, sort_policies=None,
sort_order_directions=None
): ):
""" """
Construct a search query for all users in `course_id` and return Construct a search query for all users in `course_id` and return
the Search object. the Search object.
order_by_fields specifies the fields to order by with the first element of sort_policies is an array, where the first element is the primary sort.
the array as the primary sort. Similarly, sort_order_directions corresponds Elements in the array are dicts with fields: order_by (field to sort by)
to the direction of the sort. These arrays must be of the same size. and sort_order (either 'asc' or 'desc'). Default to 'username' and 'asc'.
Raises `ValueError` if both `segments` and `ignore_segments` are provided. Raises `ValueError` if both `segments` and `ignore_segments` are provided.
""" """
if order_by_fields is None: if sort_policies is None or len(sort_policies) == 0:
order_by_fields = ['username'] sort_policies = [{
'order_by': None,
if sort_order_directions is None: 'sort_order': None
sort_order_directions = ['asc'] }]
# set default sort policy to 'username' and 'asc'
for field, default in [('order_by', 'username'), ('sort_order', 'asc')]:
if sort_policies[0][field] is None:
sort_policies[0][field] = default
# Error handling # Error handling
if segments and ignore_segments: if segments and ignore_segments:
...@@ -289,23 +292,15 @@ class RosterEntry(DocType): ...@@ -289,23 +292,15 @@ class RosterEntry(DocType):
'username', 'email', 'discussions_contributed', 'problems_attempted', 'problems_completed', 'username', 'email', 'discussions_contributed', 'problems_attempted', 'problems_completed',
'problem_attempts_per_completed', 'attempt_ratio_order', 'videos_viewed' 'problem_attempts_per_completed', 'attempt_ratio_order', 'videos_viewed'
) )
for order_by in order_by_fields: sort_order_options = ('asc', 'desc')
if order_by not in order_by_options: for sort_policy in sort_policies:
if sort_policy['order_by'] not in order_by_options:
raise ValueError("order_by value '{order_by}' must be one of: ({order_by_options})".format( raise ValueError("order_by value '{order_by}' must be one of: ({order_by_options})".format(
order_by=order_by, order_by_options=', '.join(order_by_options) order_by=sort_policy['order_by'], order_by_options=', '.join(order_by_options)
)) ))
if sort_policy['sort_order'] not in sort_order_options:
sort_order_options = ('asc', 'desc')
for sort_order in sort_order_directions:
if sort_order not in sort_order_options:
raise ValueError("sort_order value '{sort_order}' must be one of: ({sort_order_options})".format( raise ValueError("sort_order value '{sort_order}' must be one of: ({sort_order_options})".format(
sort_order=sort_order, sort_order_options=', '.join(sort_order_options) sort_order=sort_policy['sort_order'], sort_order_options=', '.join(sort_order_options)
))
if len(order_by_fields) != len(sort_order_directions):
raise ValueError("The number of items in order_by_fields '{order_by_count}' must equal that of "
"sort_order_directions '{sort_order_count}'".format(
order_by_count=len(order_by_fields), sort_order_count=len(sort_order_directions)
)) ))
search = cls.search() search = cls.search()
...@@ -326,9 +321,10 @@ class RosterEntry(DocType): ...@@ -326,9 +321,10 @@ class RosterEntry(DocType):
# construct the sort hierarchy # construct the sort hierarchy
sort_terms = [] sort_terms = []
for order_by, sort_order in zip(order_by_fields, sort_order_directions): for sort_policy in sort_policies:
sort_order = sort_policy['sort_order']
term = { term = {
order_by: { sort_policy['order_by']: {
'order': sort_order, 'order': sort_order,
'missing': '_last' if sort_order == 'asc' else '_first', # ordering of missing fields 'missing': '_last' if sort_order == 'asc' else '_first', # ordering of missing fields
} }
......
...@@ -176,17 +176,20 @@ class LearnerListView(CourseViewMixin, generics.ListAPIView): ...@@ -176,17 +176,20 @@ class LearnerListView(CourseViewMixin, generics.ListAPIView):
query_params = self.request.QUERY_PARAMS query_params = self.request.QUERY_PARAMS
order_by = query_params.get('order_by') order_by = query_params.get('order_by')
order_by_fields = [order_by] if order_by else None
sort_order = query_params.get('sort_order') sort_order = query_params.get('sort_order')
sort_order_directions = [sort_order] if sort_order else None sort_policies = [{
'order_by': order_by,
'sort_order': sort_order
}]
# Ordering by problem_attempts_per_completed can be ambiguous because # Ordering by problem_attempts_per_completed can be ambiguous because
# values could be infinite (e.g. divide by zero) if no problems were completed. # values could be infinite (e.g. divide by zero) if no problems were completed.
# Instead, secondary sorting by attempt_ratio_order will produce a sensible ordering # Instead, secondary sorting by attempt_ratio_order will produce a sensible ordering.
if order_by == 'problem_attempts_per_completed': if order_by == 'problem_attempts_per_completed':
order_by_fields.append('attempt_ratio_order') sort_policies.append({
sort_order_directions.append('asc' if sort_order == 'desc' else 'desc') 'order_by': 'attempt_ratio_order',
'sort_order': 'asc' if sort_order == 'desc' else 'desc'
})
params = { params = {
'segments': split_query_argument(query_params.get('segments')), 'segments': split_query_argument(query_params.get('segments')),
...@@ -194,8 +197,7 @@ class LearnerListView(CourseViewMixin, generics.ListAPIView): ...@@ -194,8 +197,7 @@ class LearnerListView(CourseViewMixin, generics.ListAPIView):
'cohort': query_params.get('cohort'), 'cohort': query_params.get('cohort'),
'enrollment_mode': query_params.get('enrollment_mode'), 'enrollment_mode': query_params.get('enrollment_mode'),
'text_search': query_params.get('text_search'), 'text_search': query_params.get('text_search'),
'order_by_fields': order_by_fields, 'sort_policies': sort_policies,
'sort_order_directions': sort_order_directions,
} }
# Remove None values from `params` so that we don't overwrite default # Remove None values from `params` so that we don't overwrite default
# parameter values in `get_users_in_course`. # parameter values in `get_users_in_course`.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment