Skip to content

Commit

Permalink
changes in LearnerBaseSErailizer
Browse files Browse the repository at this point in the history
  • Loading branch information
tehreem-sadat committed Nov 20, 2024
1 parent 7490447 commit ba6f8c8
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 43 deletions.
3 changes: 1 addition & 2 deletions futurex_openedx_extensions/dashboard/details/learners.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,5 @@ def get_learners_enrollments_queryset(
default=Value(False),
output_field=BooleanField(),
)
)

).select_related('user', 'user__profile')
return queryset
112 changes: 71 additions & 41 deletions futurex_openedx_extensions/dashboard/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ class LearnerBasicDetailsSerializer(ModelSerializerOptionalFields):
user_id = serializers.SerializerMethodField()
full_name = serializers.SerializerMethodField()
alternative_full_name = serializers.SerializerMethodField()
username = serializers.CharField()
username = serializers.SerializerMethodField()
national_id = serializers.SerializerMethodField()
email = serializers.EmailField()
email = serializers.SerializerMethodField()
mobile_no = serializers.SerializerMethodField()
year_of_birth = serializers.SerializerMethodField()
gender = serializers.SerializerMethodField()
gender_display = serializers.SerializerMethodField()
date_joined = serializers.DateTimeField()
last_login = serializers.DateTimeField()
date_joined = serializers.SerializerMethodField()
last_login = serializers.SerializerMethodField()

class Meta:
model = get_user_model()
Expand Down Expand Up @@ -118,6 +118,16 @@ def _is_english(text: str) -> bool:
"""
return all(ord(char) < 128 for char in text)

def _get_user(self, obj: Any = None) -> get_user_model | None: # pylint: disable=no-self-use
"""
Retrieve the associated user for the given object.
This method can be overridden in child classes to provide a different
implementation for accessing the user, depending on how the user is
related to the object (e.g., `obj.user`, `obj.profile.user`, etc.).
"""
return obj

def _get_name(self, obj: Any, alternative: bool = False) -> str:
"""
Calculate the full name and alternative full name. We have two issues in the data:
Expand All @@ -130,8 +140,8 @@ def _get_name(self, obj: Any, alternative: bool = False) -> str:
:type alternative: bool
:return: The full name or alternative full name.
"""
first_name = obj.first_name.strip()
last_name = obj.last_name.strip()
first_name = self._get_user(obj).first_name.strip() # type: ignore
last_name = self._get_user(obj).last_name.strip() # type: ignore

full_name = first_name or last_name
if first_name and last_name and not (first_name == last_name and ' ' in first_name):
Expand Down Expand Up @@ -167,20 +177,36 @@ def _get_arabic_name(self, obj: Any) -> str:
arabic_full_name = ' '.join(filter(None, (arabic_first_name, arabic_last_name)))
return (arabic_full_name or '').strip()

@staticmethod
def _get_profile_field(obj: get_user_model, field_name: str) -> Any:
def _get_profile_field(self: Any, obj: get_user_model, field_name: str) -> Any:
"""Get the profile field value."""
return getattr(obj.profile, field_name) if hasattr(obj, 'profile') and obj.profile else None
user = self._get_user(obj)
return getattr(user.profile, field_name) if hasattr(user, 'profile') and user.profile else None

@staticmethod
def _get_extra_field(obj: get_user_model, field_name: str) -> Any:
def _get_extra_field(self: Any, obj: get_user_model, field_name: str) -> Any:
"""Get the extra field value."""
return getattr(obj.extrainfo, field_name) if hasattr(obj, 'extrainfo') and obj.extrainfo else None
user = self._get_user(obj)
return getattr(user.extrainfo, field_name) if hasattr(user, 'extrainfo') and user.extrainfo else None

def get_user_id(self, obj: get_user_model) -> Any: # pylint: disable=no-self-use
"""Return user ID."""
return obj.id

def get_email(self, obj: get_user_model) -> str:
"""Return user ID."""
return self._get_user(obj).email # type: ignore

def get_username(self, obj: get_user_model) -> str:
"""Return user ID."""
return self._get_user(obj).username # type: ignore

def get_date_joined(self, obj: get_user_model) -> str:
"""Return user ID."""
return str(self._get_user(obj).date_joined) # type: ignore

def get_last_login(self, obj: get_user_model) -> str:
"""Return user ID."""
return str(self._get_user(obj).last_login) # type: ignore

def get_national_id(self, obj: get_user_model) -> Any:
"""Return national ID."""
return self._get_extra_field(obj, 'national_id')
Expand Down Expand Up @@ -210,27 +236,6 @@ def get_year_of_birth(self, obj: get_user_model) -> Any:
return self._get_profile_field(obj, 'year_of_birth')


class LearnerDetailsSerializer(LearnerBasicDetailsSerializer):
"""Serializer for learner details."""
enrolled_courses_count = serializers.SerializerMethodField()
certificates_count = serializers.SerializerMethodField()

class Meta:
model = get_user_model()
fields = LearnerBasicDetailsSerializer.Meta.fields + [
'enrolled_courses_count',
'certificates_count',
]

def get_certificates_count(self, obj: get_user_model) -> Any: # pylint: disable=no-self-use
"""Return certificates count."""
return obj.certificates_count

def get_enrolled_courses_count(self, obj: get_user_model) -> Any: # pylint: disable=no-self-use
"""Return enrolled courses count."""
return obj.courses_count


class CourseScoreAndCertificateSerializer(ModelSerializerOptionalFields):
"""
Course Score and Certificate Details Serializer
Expand Down Expand Up @@ -346,6 +351,27 @@ def _extract_exam_scores(representation_item: dict[str, Any]) -> None:
return representation


class LearnerDetailsSerializer(LearnerBasicDetailsSerializer):
"""Serializer for learner details."""
enrolled_courses_count = serializers.SerializerMethodField()
certificates_count = serializers.SerializerMethodField()

class Meta:
model = get_user_model()
fields = LearnerBasicDetailsSerializer.Meta.fields + [
'enrolled_courses_count',
'certificates_count',
]

def get_certificates_count(self, obj: get_user_model) -> Any: # pylint: disable=no-self-use
"""Return certificates count."""
return obj.certificates_count

def get_enrolled_courses_count(self, obj: get_user_model) -> Any: # pylint: disable=no-self-use
"""Return enrolled courses count."""
return obj.courses_count


class LearnerDetailsForCourseSerializer(
LearnerBasicDetailsSerializer, CourseScoreAndCertificateSerializer
): # pylint: disable=too-many-ancestors
Expand All @@ -370,13 +396,19 @@ def _get_user(self, obj: Any = None) -> get_user_model:
return obj


class LearnerEnrollmentSerializer(CourseScoreAndCertificateSerializer):
class LearnerEnrollmentSerializer(
LearnerBasicDetailsSerializer, CourseScoreAndCertificateSerializer
): # pylint: disable=too-many-ancestors
"""Serializer for learner enrollments"""
course_id = serializers.SerializerMethodField()

class Meta:
model = CourseEnrollment
fields = CourseScoreAndCertificateSerializer.Meta.fields + ['course_id']
fields = (
LearnerBasicDetailsSerializer.Meta.fields +
CourseScoreAndCertificateSerializer.Meta.fields +
['course_id']
)

def __init__(self, *args: Any, **kwargs: Any):
"""Initialize the serializer."""
Expand All @@ -389,18 +421,16 @@ def _get_course_id(self, obj: Any = None) -> CourseLocator | None:
return obj.course_id if obj else None

def _get_user(self, obj: Any = None) -> get_user_model | None:
"""Get the User. Its helper method required for CourseScoreAndCertificateSerializer"""
"""
Get the User. Its helper method required for CourseScoreAndCertificateSerializer. It also
plays important role for LearnerBasicDetailsSerializer
"""
return obj.user if obj else None

def get_course_id(self, obj: Any) -> str:
"""Get course id"""
return str(self._get_course_id(obj))

def to_representation(self, instance: Any) -> Any:
representation = LearnerBasicDetailsSerializer(self._get_user(instance)).data
representation.update(super().to_representation(instance))
return representation


class LearnerDetailsExtendedSerializer(LearnerDetailsSerializer): # pylint: disable=too-many-ancestors
"""Serializer for extended learner details."""
Expand Down

0 comments on commit ba6f8c8

Please sign in to comment.