Files
edx-platform/lms/djangoapps/program_enrollments/api/reading.py
Kyle McCormick 358f989131 Create Python API for program_enrollments: Part III
This is the third in a series of commits to create
a Python API for the LMS program_enrollments app.
It does the following:
* Creates api/ folder.
* Moves link_program_enrollments.py to api/linking.py
* Creates api/reading.py for enrollment-fetching
  functions.
* Updates rest of app to use api/reading.py when
  it was going directly through the models before.
* Other misc. cleanup (isorting, unicode_literals,
  line breaks, etc).

Still to do:
* Create api/writing.py and update app to use it instead
  of going directly through models.
* Create api/reset.py and api/expire.py, which the management
  commands call out to.

EDUCATOR-4321
2019-09-12 14:54:03 -04:00

322 lines
9.8 KiB
Python

"""
Python API functions related to reading program enrollments.
Outside of this subpackage, import these functions
from `lms.djangoapps.program_enrollments.api`.
"""
from __future__ import absolute_import, unicode_literals
from ..models import ProgramCourseEnrollment, ProgramEnrollment
_STUDENT_ARG_ERROR_MESSAGE = (
"user and external_user_key are both None; at least one must be provided."
)
_REALIZED_FILTER_ERROR_TEMPLATE = (
"{} and {} are mutually exclusive; at most one of them may be passed in as True."
)
def get_program_enrollment(
program_uuid,
user=None,
external_user_key=None,
curriculum_uuid=None,
):
"""
Get a single program enrollment.
Required arguments:
* program_uuid (UUID|str)
* At least one of:
* user (User)
* external_user_key (str)
Optional arguments:
* curriculum_uuid (UUID|str) [optional]
Returns: ProgramEnrollment
Raises: ProgramEnrollment.DoesNotExist, ProgramEnrollment.MultipleObjectsReturned
"""
if not (user or external_user_key):
raise ValueError(_STUDENT_ARG_ERROR_MESSAGE)
filters = {
"user": user,
"external_user_key": external_user_key,
"curriculum_uuid": curriculum_uuid,
}
return ProgramEnrollment.objects.get(
program_uuid=program_uuid, **_remove_none_values(filters)
)
def get_program_course_enrollment(
program_uuid,
course_key,
user=None,
external_user_key=None,
curriculum_uuid=None,
):
"""
Get a single program-course enrollment.
Required arguments:
* program_uuid (UUID|str)
* course_key (CourseKey|str)
* At least one of:
* user (User)
* external_user_key (str)
Optional arguments:
* curriculum_uuid (UUID|str) [optional]
Returns: ProgramCourseEnrollment
Raises:
* ProgramCourseEnrollment.DoesNotExist
* ProgramCourseEnrollment.MultipleObjectsReturned
"""
if not (user or external_user_key):
raise ValueError(_STUDENT_ARG_ERROR_MESSAGE)
filters = {
"program_enrollment__user": user,
"program_enrollment__external_user_key": external_user_key,
"program_enrollment__curriculum_uuid": curriculum_uuid,
}
return ProgramCourseEnrollment.objects.get(
program_enrollment__program_uuid=program_uuid,
course_key=course_key,
**_remove_none_values(filters)
)
def fetch_program_enrollments(
program_uuid,
curriculum_uuids=None,
users=None,
external_user_keys=None,
program_enrollment_statuses=None,
realized_only=False,
waiting_only=False,
):
"""
Fetch program enrollments for a specific program.
Required argument:
* program_uuid (UUID|str)
Optional arguments:
* curriculum_uuids (iterable[UUID|str])
* users (iterable[User])
* external_user_keys (iterable[str])
* program_enrollment_statuses (iterable[str])
* realized_only (bool)
* waiting_only (bool)
Optional arguments are used as filtersets if they are not None.
At most one of (realized_only, waiting_only) may be provided.
Returns: queryset[ProgramEnrollment]
"""
if realized_only and waiting_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("realized_only", "waiting_only")
)
filters = {
"curriculum_uuid__in": curriculum_uuids,
"user__in": users,
"external_user_key__in": external_user_keys,
"status__in": program_enrollment_statuses,
}
if realized_only:
filters["user__isnull"] = False
if waiting_only:
filters["user__isnull"] = True
return ProgramEnrollment.objects.filter(
program_uuid=program_uuid, **_remove_none_values(filters)
)
def fetch_program_course_enrollments(
program_uuid,
course_key,
curriculum_uuids=None,
users=None,
external_user_keys=None,
program_enrollment_statuses=None,
active_only=False,
inactive_only=False,
realized_only=False,
waiting_only=False,
):
"""
Fetch program-course enrollments for a specific program and course run.
Required argument:
* program_uuid (UUID|str)
* course_key (CourseKey|str)
Optional arguments:
* curriculum_uuids (iterable[UUID|str])
* users (iterable[User])
* external_user_keys (iterable[str])
* program_enrollment_statuses (iterable[str])
* active_only (bool)
* inactive_only (bool)
* realized_only (bool)
* waiting_only (bool)
Optional arguments are used as filtersets if they are not None.
At most one of (realized_only, waiting_only) may be provided.
At most one of (active_only, inactive_only) may be provided.
Returns: queryset[ProgramCourseEnrollment]
"""
if active_only and inactive_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("active_only", "inactive_only")
)
if realized_only and waiting_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("realized_only", "waiting_only")
)
filters = {
"program_enrollment__curriculum_uuid__in": curriculum_uuids,
"program_enrollment__user__in": users,
"program_enrollment__external_user_key__in": external_user_keys,
"program_enrollment__status__in": program_enrollment_statuses,
}
if active_only:
filters["status"] = "active"
if inactive_only:
filters["status"] = "inactive"
if realized_only:
filters["program_enrollment__user__isnull"] = False
if waiting_only:
filters["program_enrollment__user__isnull"] = True
return ProgramCourseEnrollment.objects.filter(
program_enrollment__program_uuid=program_uuid,
course_key=course_key,
**_remove_none_values(filters)
)
def fetch_program_enrollments_by_student(
user=None,
external_user_key=None,
program_uuids=None,
curriculum_uuids=None,
program_enrollment_statuses=None,
realized_only=False,
waiting_only=False,
):
"""
Fetch program enrollments for a specific student.
Required arguments (at least one must be provided):
* user (User)
* external_user_key (str)
Optional arguments:
* provided_uuids (iterable[UUID|str])
* curriculum_uuids (iterable[UUID|str])
* program_enrollment_statuses (iterable[str])
* realized_only (bool)
* waiting_only (bool)
Optional arguments are used as filtersets if they are not None.
At most one of (realized_only, waiting_only) may be provided.
Returns: queryset[ProgramEnrollment]
"""
if not (user or external_user_key):
raise ValueError(_STUDENT_ARG_ERROR_MESSAGE)
if realized_only and waiting_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("realized_only", "waiting_only")
)
filters = {
"user": user,
"external_user_key": external_user_key,
"program_uuid__in": program_uuids,
"curriculum_uuid__in": curriculum_uuids,
"status__in": program_enrollment_statuses,
}
if realized_only:
filters["user__isnull"] = False
if waiting_only:
filters["user__isnull"] = True
return ProgramEnrollment.objects.filter(**_remove_none_values(filters))
def fetch_program_course_enrollments_by_student(
user=None,
external_user_key=None,
program_uuids=None,
curriculum_uuids=None,
course_keys=None,
program_enrollment_statuses=None,
active_only=False,
inactive_only=False,
realized_only=False,
waiting_only=False,
):
"""
Fetch program-course enrollments for a specific student.
Required arguments (at least one must be provided):
* user (User)
* external_user_key (str)
Optional arguments:
* provided_uuids (iterable[UUID|str])
* curriculum_uuids (iterable[UUID|str])
* course_keys (iterable[CourseKey|str])
* program_enrollment_statuses (iterable[str])
* realized_only (bool)
* waiting_only (bool)
Optional arguments are used as filtersets if they are not None.
At most one of (realized_only, waiting_only) may be provided.
At most one of (active_only, inactive_only) may be provided.
Returns: queryset[ProgramCourseEnrollment]
"""
if not (user or external_user_key):
raise ValueError(_STUDENT_ARG_ERROR_MESSAGE)
if active_only and inactive_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("active_only", "inactive_only")
)
if realized_only and waiting_only:
raise ValueError(
_REALIZED_FILTER_ERROR_TEMPLATE.format("realized_only", "waiting_only")
)
filters = {
"program_enrollment__user": user,
"program_enrollment__external_user_key": external_user_key,
"program_enrollment__program_uuid__in": program_uuids,
"program_enrollment__curriculum_uuid__in": curriculum_uuids,
"course_key__in": course_keys,
"program_enrollment__status__in": program_enrollment_statuses,
}
if active_only:
filters["status"] = "active"
if inactive_only:
filters["status"] = "inactive"
if realized_only:
filters["program_enrollment__user__isnull"] = False
if waiting_only:
filters["program_enrollment__user__isnull"] = True
return ProgramCourseEnrollment.objects.filter(**_remove_none_values(filters))
def _remove_none_values(dictionary):
"""
Return a dictionary where key-value pairs with `None` as the value
are removed.
"""
return {
key: value for key, value in dictionary.items() if value is not None
}