Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions openedx/core/djangoapps/enrollments/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import logging

from django.db.models import Prefetch
from rest_framework import serializers

from common.djangoapps.course_modes.models import CourseMode
Expand All @@ -12,6 +13,17 @@
log = logging.getLogger(__name__)


def with_verified_mode_prefetch(queryset):
"""Prefetch verified modes so enrollment serialization avoids per-row lookups."""
return queryset.select_related("user", "course").prefetch_related(
Prefetch(
"course__modes",
queryset=CourseMode.objects.filter(mode_slug=CourseMode.VERIFIED),
to_attr="prefetched_verified_modes",
)
)


class StringListField(serializers.CharField):
"""Custom Serializer for turning a comma delimited string into a list.

Expand Down Expand Up @@ -69,7 +81,7 @@ def get_pacing_type(self, obj):


class CourseEnrollmentSerializer(serializers.ModelSerializer):
"""Serializes CourseEnrollment models
"""Serializes CourseEnrollment models.

Aggregates all data from the Course Enrollment table, and pulls in the serialization for
the Course block and course modes, to give a complete representation of course enrollment.
Expand All @@ -78,14 +90,64 @@ class CourseEnrollmentSerializer(serializers.ModelSerializer):

course_details = CourseSerializer(source="course_overview")
user = serializers.SerializerMethodField("get_username")
access_expiration_date = serializers.SerializerMethodField()
is_audit_with_expiring_upgrade = serializers.SerializerMethodField()

Comment thread
GBalaji3320 marked this conversation as resolved.
def get_username(self, model):
"""Retrieves the username from the associated model."""
return model.username

def _get_verified_mode(self, obj):
"""Retrieve the verified mode for this enrollment's course."""
course_overview = obj.course_overview
if course_overview is None:
return None

prefetched_verified_modes = getattr(course_overview, "prefetched_verified_modes", None)
if prefetched_verified_modes is not None:
return prefetched_verified_modes[0] if prefetched_verified_modes else None

verified_mode_by_course = self.context.setdefault("verified_mode_by_course", {})
if obj.course_id not in verified_mode_by_course:
verified_mode_by_course[obj.course_id] = CourseMode.objects.filter(
course_id=obj.course_id,
mode_slug=CourseMode.VERIFIED,
).first()

return verified_mode_by_course[obj.course_id]

def get_access_expiration_date(self, obj):
"""Return expiration date for audit enrollments."""

if obj.mode != CourseMode.AUDIT:
return None

verified_mode = self._get_verified_mode(obj)

if verified_mode and verified_mode.expiration_datetime:
return verified_mode.expiration_datetime.isoformat().replace('+00:00', 'Z')
Comment thread
GBalaji3320 marked this conversation as resolved.

return None

def get_is_audit_with_expiring_upgrade(self, obj):
"""Return whether an audit enrollment has a verified upgrade expiration."""
if obj.mode != CourseMode.AUDIT:
return False

verified_mode = self._get_verified_mode(obj)
return bool(verified_mode and verified_mode.expiration_datetime)
Comment thread
GBalaji3320 marked this conversation as resolved.

class Meta:
model = CourseEnrollment
fields = ("created", "mode", "is_active", "course_details", "user")
fields = (
"created",
"mode",
"is_active",
"course_details",
"user",
"access_expiration_date",
"is_audit_with_expiring_upgrade",
)
lookup_field = "username"


Expand All @@ -106,7 +168,7 @@ class Meta(CourseEnrollmentSerializer.Meta):


class ModeSerializer(serializers.Serializer): # pylint: disable=abstract-method
"""Serializes a course's 'Mode' tuples
"""Serializes a course's 'Mode' tuples.

Returns a serialized representation of the modes available for course enrollment. The course
modes models are designed to return a tuple instead of the model object itself. This serializer
Expand Down
Loading
Loading