@@ -335,6 +335,20 @@ def degree_rules_filter(queryset, rule_ids):
335335 return queryset .filter (query )
336336
337337
338+ def department_filter (queryset , departments ):
339+ """
340+ Filters courses by department code(s) with OR logic.
341+ :param queryset: Course queryset
342+ :param departments: Comma-separated department codes (e.g. "CIS,NETS,ESE")
343+ """
344+ if not departments :
345+ return queryset
346+ codes = [code .strip ().upper () for code in departments .split ("," ) if code .strip ()]
347+ if not codes :
348+ return queryset
349+ return queryset .filter (department__code__in = codes )
350+
351+
338352class CourseSearchFilterBackend (filters .BaseFilterBackend ):
339353 def filter_queryset (self , request , queryset , view ):
340354 filters = {
@@ -347,6 +361,7 @@ def filter_queryset(self, request, queryset, view):
347361 "difficulty" : bound_filter ("difficulty" ),
348362 "is_open" : is_open_filter ,
349363 "rule_ids" : degree_rules_filter ,
364+ "departments" : department_filter ,
350365 }
351366 for field , filter_func in filters .items ():
352367 param = request .query_params .get (field )
@@ -367,7 +382,19 @@ def filter_queryset(self, request, queryset, view):
367382 if len (meeting_query ) > 0 :
368383 queryset = meeting_filter (queryset , meeting_query )
369384
370- return queryset .distinct ("full_code" ) # TODO: THIS COULD BE A BREAKING CHANGE FOR PCX
385+ queryset = queryset .distinct ("full_code" ) # TODO: THIS COULD BE A BREAKING CHANGE FOR PCX
386+
387+ # Apply index-based pagination (indices parameter, e.g. "11-20")
388+ indices_param = request .query_params .get ("indices" )
389+ if indices_param :
390+ parts = indices_param .split ("-" )
391+ if len (parts ) == 2 and parts [0 ].isdigit () and parts [1 ].isdigit ():
392+ start = int (parts [0 ])
393+ end = int (parts [1 ])
394+ if start >= 0 and end >= start :
395+ queryset = queryset [start :end + 1 ]
396+
397+ return queryset
371398
372399 def get_schema_operation_parameters (self , view ):
373400 return [
@@ -527,6 +554,31 @@ def get_schema_operation_parameters(self, view):
527554 "schema" : {"type" : "integer" },
528555 "example" : "242" ,
529556 },
557+ {
558+ "name" : "departments" ,
559+ "required" : False ,
560+ "in" : "query" ,
561+ "description" : (
562+ "Filter courses by department code(s). Accepts a comma-separated "
563+ "list of department codes with OR logic (i.e. a course is included "
564+ "if it belongs to any of the specified departments)."
565+ ),
566+ "schema" : {"type" : "string" },
567+ "example" : "CIS,NETS,ESE" ,
568+ },
569+ {
570+ "name" : "indices" ,
571+ "required" : False ,
572+ "in" : "query" ,
573+ "description" : (
574+ "Return only the courses at the specified index range from the "
575+ "sorted results. The range should be specified as `start-end` "
576+ "(0-indexed, inclusive on both ends). Useful for pagination / "
577+ "chunking large result sets."
578+ ),
579+ "schema" : {"type" : "string" },
580+ "example" : "0-19" ,
581+ },
530582 {
531583 "name" : "is_open" ,
532584 "required" : False ,
0 commit comments