serializers.py 9.71 KB
Newer Older
1 2 3 4
from django.contrib.auth import get_user_model
from rest_framework import serializers

from .videos.serializers import VideoSerializer
Matheus Miranda's avatar
Matheus Miranda committed
5
from courses_learning_objects.serializers import LearningObjectSerializer as ActivitySerializer
6 7 8
from .models import (
    Course,
    CourseProfessor,
9 10
    ProfessorMessage,
    ProfessorMessageRead,
11
    CourseTrack,
Matheus Miranda's avatar
Matheus Miranda committed
12 13 14
    CourseStudent,
    Unit,
    Lesson
15
)
16 17 18 19


User = get_user_model()

20

21 22 23 24 25
class SimpleUserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        # The model must have image, biography and name fields
26 27 28
        # FIXME remove email from here, couse this way, one user can
        # all users email.
        fields = ('id', 'image', 'name', 'biography', 'username', 'email')
29 30 31 32 33 34 35 36 37 38


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()
39
    track = serializers.SerializerMethodField()
40 41
    is_user_enrolled = serializers.SerializerMethodField()
    enroll_course_url = serializers.SerializerMethodField()
42
    user_done_units = serializers.SerializerMethodField()
43 44 45

    class Meta:
        model = Course
46 47 48 49 50 51
        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',
52
                  'is_user_enrolled', 'enroll_course_url', 'user_done_units')
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

    @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)

69 70 71 72 73 74
    def get_is_user_enrolled(self, obj):
        user = None
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user

75 76 77 78 79 80 81 82 83 84
        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
85 86

    def get_enroll_course_url(self, obj):
Matheus Miranda's avatar
Matheus Miranda committed
87 88 89 90 91 92 93
        user = None
        request = self.context.get("request")
        if request and hasattr(request, "user"):
            user = request.user
        else:
            return ''

94
        course = obj
Matheus Miranda's avatar
Matheus Miranda committed
95
        if course.is_enrolled(user):
96 97 98
            return 'resume_course'
        if course.status == 'draft':
            return 'courses'
Matheus Miranda's avatar
Matheus Miranda committed
99 100
        if user.accepted_terms or not settings.TERMS_ACCEPTANCE_REQUIRED:
            course.enroll_student(user)
101 102 103 104 105 106 107
            if course.has_started and course.first_lesson():
                return 'lesson'
            else:
                return 'course_home'
        else:
            'accept_terms'

108 109 110 111 112 113
    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 {}

114 115 116 117 118 119 120 121 122 123 124 125 126
    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
127 128 129 130


class BasicCourseSerializer(serializers.ModelSerializer):
    home_thumbnail_url = serializers.SerializerMethodField()
131
    professors = SimpleUserSerializer(read_only=True, many=True)
132 133 134 135 136 137 138 139 140 141 142 143 144 145

    class Meta:
        model = Course
        fields = (
            "id",
            "slug",
            "name",
            "status",
            "home_thumbnail_url",
            "start_date",
            "home_published",
            "has_started",
            "min_percent_to_complete",
            "is_public",
146
            "professors"
147 148 149 150 151 152 153 154
        )

    @staticmethod
    def get_home_thumbnail_url(obj):
        if obj.home_thumbnail:
            return obj.home_thumbnail.url
        return ''

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

class BasicCourseProfessorSerializer(serializers.ModelSerializer):

    user = SimpleUserSerializer(read_only=True)

    class Meta:
        fields = (
            'id',
            'course',
            'user',
            'role',
        )
        model = CourseProfessor


170 171 172 173 174 175 176 177 178 179 180 181 182
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)
183
    
184 185 186
    class Meta:
        model = ProfessorMessage
        fields = ('id', 'course', 'course_name', 'course_slug', 'professor',
Bruno Martin's avatar
Bruno Martin committed
187 188 189
                  'users', 'subject', 'message', 'date', 'is_read', 'groups', 'classes',
                  'classrooms',
        )
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

    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
Matheus Miranda's avatar
Matheus Miranda committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288


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