from django.contrib.auth import get_user_model from rest_framework import serializers from .videos.serializers import VideoSerializer from courses_learning_objects.serializers import LearningObjectSerializer as ActivitySerializer from .models import ( Course, CourseProfessor, ProfessorMessage, ProfessorMessageRead, CourseTrack, CourseStudent, Unit, Lesson ) User = get_user_model() class SimpleUserSerializer(serializers.ModelSerializer): class Meta: model = User # The model must have image, biography and name fields # FIXME remove email from here, couse this way, one user can # all users email. fields = ('id', 'image', 'name', 'biography', 'username', 'email') class CourseSerializer(serializers.ModelSerializer): intro_video = VideoSerializer(required=False) home_thumbnail_url = serializers.SerializerMethodField() professors = SimpleUserSerializer(read_only=True, many=True) is_user_assistant = serializers.SerializerMethodField() is_user_coordinator = serializers.SerializerMethodField() is_assistant_or_coordinator = serializers.SerializerMethodField() track = serializers.SerializerMethodField() is_user_enrolled = serializers.SerializerMethodField() enroll_course_url = serializers.SerializerMethodField() user_done_units = serializers.SerializerMethodField() class Meta: model = Course fields = ('id', 'slug', 'name', 'intro_video', 'application', 'requirement', 'abstract', 'structure', 'workload', 'status', 'is_public', 'thumbnail_url', 'home_thumbnail_url', 'home_position', 'start_date', 'home_published', 'authors_names', 'has_started', 'min_percent_to_complete', 'is_user_assistant', 'is_user_coordinator', 'is_assistant_or_coordinator', 'professors', 'track', 'forum_id', 'is_user_enrolled', 'enroll_course_url', 'user_done_units') @staticmethod def get_home_thumbnail_url(obj): if obj.home_thumbnail: return obj.home_thumbnail.url return '' def get_is_user_assistant(self, obj): return obj.is_course_assistant(self.context['request'].user) def get_is_user_coordinator(self, obj): return obj.is_course_coordinator(self.context['request'].user) def get_is_assistant_or_coordinator(self, obj): return obj.is_assistant_or_coordinator(self.context['request'].user) def get_is_user_enrolled(self, obj): user = None request = self.context.get("request") if request and hasattr(request, "user"): user = request.user return CourseStudent.objects.filter(course=obj, user=user).exists() def get_user_done_units(self, obj): user = None request = self.context.get("request") if request and hasattr(request, "user"): user = request.user if CourseStudent.objects.filter(course=obj, user=user).exists(): return CourseStudent.objects.filter(course=obj, user=user).first().units_done def get_enroll_course_url(self, obj): user = None request = self.context.get("request") if request and hasattr(request, "user"): user = request.user else: return '' course = obj if course.is_enrolled(user): return 'resume_course' if course.status == 'draft': return 'courses' if user.accepted_terms or not settings.TERMS_ACCEPTANCE_REQUIRED: course.enroll_student(user) if course.has_started and course.first_lesson(): return 'lesson' else: return 'course_home' else: 'accept_terms' def get_track(self, obj): course_track = CourseTrack.objects.filter(courses=obj) if course_track: return {'name': course_track.first().name, 'home_position': course_track.first().home_position } return {} def update(self, instance, validated_data): intro_video_data = validated_data.pop('intro_video', None) course = super(CourseSerializer, self).update(instance, validated_data) if intro_video_data: intro_video_ser = VideoSerializer(course.intro_video, data=intro_video_data) if intro_video_ser.is_valid(): intro_video = intro_video_ser.save() course.intro_video = intro_video course.save() return course class BasicCourseSerializer(serializers.ModelSerializer): home_thumbnail_url = serializers.SerializerMethodField() professors = SimpleUserSerializer(read_only=True, many=True) class Meta: model = Course fields = ( "id", "slug", "name", "status", "home_thumbnail_url", "start_date", "home_published", "has_started", "min_percent_to_complete", "is_public", "professors" ) @staticmethod def get_home_thumbnail_url(obj): if obj.home_thumbnail: return obj.home_thumbnail.url return '' class BasicCourseProfessorSerializer(serializers.ModelSerializer): user = SimpleUserSerializer(read_only=True) class Meta: fields = ( 'id', 'course', 'user', 'role', ) model = CourseProfessor class ProfessorMessageReadSerializer(serializers.ModelSerializer): class Meta: model = ProfessorMessageRead fields = ('id', 'message', 'is_read') class ProfessorMessageSerializer(serializers.ModelSerializer): professor = SimpleUserSerializer(read_only=True) course_slug = serializers.SerializerMethodField(read_only=True) course_name = serializers.SerializerMethodField(read_only=True) is_read = serializers.SerializerMethodField(read_only=True) class Meta: model = ProfessorMessage fields = ('id', 'course', 'course_name', 'course_slug', 'professor', 'users', 'subject', 'message', 'date', 'is_read', 'groups', 'classes', 'classrooms', ) def get_course_slug(self, obj): try: return obj.course.slug except AttributeError as e: return '' # no course is associated with this message def get_course_name(self, obj): try: return obj.course.name except AttributeError as e: return '' # no course is associated with this message def get_is_read(self, obj): try: read_state = ProfessorMessageRead.objects.get(user=self.context['request'].user, message=obj) return read_state.is_read except ProfessorMessageRead.DoesNotExist as e: return False class UnitSerializer(serializers.ModelSerializer): video = VideoSerializer(required=False, allow_null=True) activities = ActivitySerializer(many=True, required=False, allow_null=True) class Meta: model = Unit fields = ('id', 'title', 'video', 'activities', 'side_notes', 'position', 'chat_room',) class LessonSerializer(serializers.ModelSerializer): units = UnitSerializer(many=True) is_course_last_lesson = serializers.BooleanField(read_only=True) thumbnail_url = serializers.ReadOnlyField() class Meta: model = Lesson fields = ('id', 'course', 'is_course_last_lesson', 'desc', 'name', 'notes', 'position', 'slug', 'status', 'units', 'thumbnail_url') def update(self, instance, validated_data): units = self.update_units(self.initial_data.get('units'), instance) for old_unit in instance.units.all(): if old_unit not in units: old_unit.delete() else: new_activities = units[units.index(old_unit)].activities if old_unit.activities != new_activities: for activity in old_unit.activities: if activity not in new_activities: activity.delete() validated_data.pop('units') return super(LessonSerializer, self).update(instance, validated_data) def create(self, validated_data): units_data = validated_data.pop('units') new_lesson = super(LessonSerializer, self).create(validated_data) # units_data = self.initial_data.get('units') self.update_units(units_data, new_lesson) return new_lesson @classmethod def update_units(cls, units_data, lesson): units = [] for unit_data in units_data: activities_data = unit_data.pop('activities', None) unit_data.pop('lesson', None) video_data = unit_data.pop('video', None) if video_data: video = Video(**video_data) video.save() else: video = None unit = Unit(lesson=lesson, video=video, **unit_data) unit.save() if activities_data: activities = [] for activity_data in activities_data: activity_id = activity_data.pop('id', None) activity, _ = Activity.objects.get_or_create(id=activity_id) activity.comment = activity_data.get('comment', None) activity.data = activity_data.get('data', None) activity.expected = activity_data.get('expected', None) activity.type = activity_data.get('type', None) activity.unit = unit activity.save() activities.append(activity) unit.activities.set(activities) units.append(unit) return units