From e35c17aae129b472bc7281bc1de101db92853fed Mon Sep 17 00:00:00 2001 From: Tehreem Sadat Date: Thu, 21 Nov 2024 01:43:12 +1300 Subject: [PATCH] changes in LearnerBaseSErailizer --- .../dashboard/details/learners.py | 3 +- .../dashboard/serializers.py | 107 +++++++++++------- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/futurex_openedx_extensions/dashboard/details/learners.py b/futurex_openedx_extensions/dashboard/details/learners.py index 44b88b12..67b6310b 100644 --- a/futurex_openedx_extensions/dashboard/details/learners.py +++ b/futurex_openedx_extensions/dashboard/details/learners.py @@ -310,6 +310,5 @@ def get_learners_enrollments_queryset( default=Value(False), output_field=BooleanField(), ) - ) - + ).select_related('user', 'user__profile') return queryset diff --git a/futurex_openedx_extensions/dashboard/serializers.py b/futurex_openedx_extensions/dashboard/serializers.py index b93e88dd..7dba0ef4 100644 --- a/futurex_openedx_extensions/dashboard/serializers.py +++ b/futurex_openedx_extensions/dashboard/serializers.py @@ -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() @@ -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: @@ -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): @@ -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') @@ -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 @@ -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 @@ -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.""" @@ -396,11 +428,6 @@ 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."""