Skip to content

Commit 7a96595

Browse files
feat: add sort order to cohorts endpoint (#38149)
1 parent 056acff commit 7a96595

3 files changed

Lines changed: 68 additions & 4 deletions

File tree

openedx/core/djangoapps/course_groups/cohorts.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,14 +319,16 @@ def migrate_cohort_settings(course):
319319
return cohort_settings
320320

321321

322-
def get_course_cohorts(course=None, course_id=None, assignment_type=None):
322+
def get_course_cohorts(course=None, course_id=None, assignment_type=None, ordering='asc'):
323323
"""
324324
Get a list of all the cohorts in the given course. This will include auto cohorts,
325325
regardless of whether or not the auto cohorts include any users.
326326
327327
Arguments:
328328
course: the course for which cohorts should be returned
329329
assignment_type: cohort assignment type
330+
ordering: sort direction for results by name. Use 'desc' for descending order.
331+
Any other value (including the default 'asc') results in ascending order.
330332
331333
Returns:
332334
A list of CourseUserGroup objects. Empty if there are no cohorts. Does
@@ -343,6 +345,11 @@ def get_course_cohorts(course=None, course_id=None, assignment_type=None):
343345
group_type=CourseUserGroup.COHORT
344346
)
345347
query_set = query_set.filter(cohort__assignment_type=assignment_type) if assignment_type else query_set
348+
ordering = ordering.lower()
349+
if ordering not in ('asc', 'desc'):
350+
raise ValueError(f"Invalid ordering value '{ordering}'. Must be 'asc' or 'desc'.")
351+
sort_field = '-name' if ordering == 'desc' else 'name'
352+
query_set = query_set.order_by(sort_field)
346353
return list(query_set)
347354

348355

openedx/core/djangoapps/course_groups/tests/test_api_views.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,49 @@ def test_patch_cohort_with_group_id_missing_partition_id(self):
583583
assert data['developer_message'] == 'If group_id is specified, user_partition_id must also be specified.'
584584
assert data['error_code'] == 'missing-user-partition-id'
585585

586+
def test_get_cohorts_default_ordering(self):
587+
"""
588+
Test that cohorts are returned in ascending alphabetical order by default.
589+
"""
590+
cohorts.add_cohort(self.course_key, "Zebra", "manual")
591+
cohorts.add_cohort(self.course_key, "Alpha", "manual")
592+
cohorts.add_cohort(self.course_key, "Mango", "manual")
593+
594+
path = reverse('api_cohorts:cohort_handler', kwargs={'course_key_string': self.course_str})
595+
self.client.login(username=self.staff_user.username, password=self.password)
596+
response = self.client.get(path=path)
597+
598+
assert response.status_code == 200
599+
names = [c['name'] for c in response.json()]
600+
assert names == ['Alpha', 'Mango', 'Zebra']
601+
602+
def test_get_cohorts_desc_ordering(self):
603+
"""
604+
Test that cohorts are returned in descending alphabetical order when ordering=desc.
605+
"""
606+
cohorts.add_cohort(self.course_key, "Zebra", "manual")
607+
cohorts.add_cohort(self.course_key, "Alpha", "manual")
608+
cohorts.add_cohort(self.course_key, "Mango", "manual")
609+
610+
path = reverse('api_cohorts:cohort_handler', kwargs={'course_key_string': self.course_str})
611+
self.client.login(username=self.staff_user.username, password=self.password)
612+
response = self.client.get(path=path, data={'ordering': 'desc'})
613+
614+
assert response.status_code == 200
615+
names = [c['name'] for c in response.json()]
616+
assert names == ['Zebra', 'Mango', 'Alpha']
617+
618+
def test_get_cohorts_invalid_ordering(self):
619+
"""
620+
Test that an invalid ordering value returns a 400 error.
621+
"""
622+
path = reverse('api_cohorts:cohort_handler', kwargs={'course_key_string': self.course_str})
623+
self.client.login(username=self.staff_user.username, password=self.password)
624+
response = self.client.get(path=path, data={'ordering': 'invalid'})
625+
626+
assert response.status_code == 400
627+
assert response.json().get('error_code') == 'invalid-ordering-value'
628+
586629
def test_patch_cohort_with_name_only(self):
587630
"""
588631
Test that PATCH with only name is now valid (previously required assignment_type too).

openedx/core/djangoapps/course_groups/views.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,18 @@ class CohortHandler(DeveloperErrorViewMixin, APIPermissions):
532532
533533
**Example Requests**:
534534
535-
GET /api/cohorts/v1/courses/{course_id}/cohorts
536-
POST /api/cohorts/v1/courses/{course_id}/cohorts
535+
GET /api/cohorts/v1/courses/{course_id}/cohorts/
536+
GET /api/cohorts/v1/courses/{course_id}/cohorts/?ordering=asc
537+
GET /api/cohorts/v1/courses/{course_id}/cohorts/?ordering=desc
538+
POST /api/cohorts/v1/courses/{course_id}/cohorts/
537539
GET /api/cohorts/v1/courses/{course_id}/cohorts/{cohort_id}
538540
PATCH /api/cohorts/v1/courses/{course_id}/cohorts/{cohort_id}
539541
542+
**GET Query Parameters**
543+
544+
* ordering (optional): Sort direction for the cohort list by name. Accepted values are
545+
"asc" (ascending, default) and "desc" (descending). Returns HTTP 400 for invalid values.
546+
540547
**POST Request Values**
541548
542549
* name (required): The string identifier for a cohort.
@@ -575,7 +582,14 @@ def get(self, request, course_key_string, cohort_id=None):
575582
"""
576583
course_key, course = _get_course_with_access(request, course_key_string, 'load')
577584
if not cohort_id:
578-
all_cohorts = cohorts.get_course_cohorts(course)
585+
ordering = request.query_params.get('ordering', 'asc').lower()
586+
if ordering not in ('asc', 'desc'):
587+
raise self.api_error(
588+
status.HTTP_400_BAD_REQUEST,
589+
'Invalid ordering value. Must be "asc" or "desc".',
590+
'invalid-ordering-value'
591+
)
592+
all_cohorts = cohorts.get_course_cohorts(course, ordering=ordering)
579593
paginator = NamespacedPageNumberPagination()
580594
paginator.max_page_size = MAX_PAGE_SIZE
581595
page = paginator.paginate_queryset(all_cohorts, request)

0 commit comments

Comments
 (0)