Пример #1
0
    def _update_last_visited_sequential(self, request, course, chapter_id, sequential_id, modification_date):
        '''
        course -- xmodule
        '''
        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
            course.id, request.user, course, depth=2)
        try:
            chapter_descriptor = get_item(course.id, 'chapter', chapter_id)
            sequential_descriptor = get_item(course.id, 'sequential', sequential_id)
        except ItemNotFoundError:
            raise error.Error(status=status.HTTP_404_NOT_FOUND)
        course_descriptor = course
        course = get_module_for_descriptor(
                request.user, request, course_descriptor, field_data_cache, course.id)
        chapter = get_module_for_descriptor(
                request.user, request, chapter_descriptor, field_data_cache, course.id)
        sequential = get_module_for_descriptor(
                request.user, request, sequential_descriptor, field_data_cache, course.id)
        if modification_date:
            key = KeyValueStore.Key(
                scope=Scope.user_state,
                user_id=request.user.id,
                block_scope_id=course.location,
                field_name=None
            )
            student_module = field_data_cache.find(key)
            if student_module:
                original_store_date = student_module.modified
                if modification_date < original_store_date:
                    # old modification date so skip update
                    return self._get_course_info(request, course)

        self.save_sequential_position(course, chapter, sequential)
        return self._get_course_info(request, course)
Пример #2
0
    def get(self, request, course_id, sequential_id, format=None):
        """ Get vertical list of the current chapter. """
        if not Course.objects.filter(course_id=course_id):
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not CourseEnrollment.is_enrolled(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        param = {
            'category': request.GET.get('category', 'video'),
        }
        sequential = get_item(course_id, "sequential", sequential_id)
        verticals = [get_item(course_id, "vertical", vertical_id)
                     for vertical_id in _get_item_id_list(sequential.children, "vertical")]
        now = datetime.now(UTC)
        verticals = filter(lambda x: x and x.start < now, verticals)

        for vertical in verticals:
            children = [get_item(course_id, param['category'], item_id)
                        for item_id in _get_item_id_list(vertical.children, param['category'])]
            children = filter(lambda x: x and x.start < now, children)
            vertical.children = children

        result = {
            "verticals": VerticalsWithChildrenSerializer(course_id, verticals, many=True).data
        }

        return Response(result)
Пример #3
0
    def get(self, request, course_id, chapter_id, format=None):
        """ Get sequential list of the current chapter. """
        if not Course.objects.filter(course_id=course_id)[0]:
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not CourseEnrollment.is_enrolled(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        chapter = get_item(course_id, "chapter", chapter_id)
        sequentials = [get_item(course_id, "sequential", sequential_id)
                       for sequential_id in _get_item_id_list(chapter.children, "sequential")]
        now = datetime.now(UTC)
        sequentials = filter(lambda x: x and x.start < now, sequentials)

        result = {
            "sequentials": SequentialSerializer(sequentials, many=True).data
        }
        return Response(result)
Пример #4
0
    def get(self, request, course_name, format=None):
        """ Get course navigational elements """
        course = get_course(course_name)
        now = datetime.now(UTC())

        # try:
        #     courses = CourseEnrollment.objects.get(
        #         user=request.user, course_id=course_name, is_active=True)
        # except:
        #     return Response(status=status.HTTP_404_NOT_FOUND)

        is_enrolled = CourseEnrollment.is_enrolled(request.user, course_name)
        if not is_enrolled:
            return Response(status=status.HTTP_404_NOT_FOUND)

        result = {
            "success": True,
            "course": {
                "display_name": course.display_name,
                "location": str(course.location),
                "start": course.start,
                "children": _get_children(course_name, course.children, 'chapter', now),
            }
        }

        chapters = result['course']['children']
        for chapter in chapters:
            sequentials = chapter['children'] = _get_children(
                course_name, chapter['children'], 'sequential', now)
            for sequential in sequentials:
                verticals = sequential['children'] = _get_children(
                    course_name, sequential['children'], 'vertical', now)
                for vertical in verticals:
                    children = [get_item(course_name, 'video', item_id) for item_id in _get_item_id_list(
                        vertical['children'], 'video')]
                    children = filter(lambda x: x and x.start < now, children)
                    vertical['children'] = []
                    course_key = SlashSeparatedCourseKey.from_string(course_name)
                    for video in children:
                        data = {
                            'display_name': video.display_name,
                            'location': str(video.location),
                            'start': video.start,
                            'track_zh': get_track_zh(video, course_key),
                            'track_en': get_track_en(video, course_key),
                            'source': get_video_source(video),
                        }
                        try:
                            ccsource = video.ccsource.strip()
                            data['length'] = VideoInfo.objects.get(
                                vid=ccsource).duration
                        except:
                            data['length'] = 0

                        vertical['children'].append(data)

        return Response(result)
Пример #5
0
    def get(self, request, course_id, vertical_id, format=None):
        """ Get vertical list of the current chapter. """
        if not Course.objects.filter(course_id=course_id)[0]:
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not CourseEnrollment.is_enrolled(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        param = {
            'category': request.GET.get('category', 'video'),
        }

        vertical = get_item(course_id, "vertical", vertical_id)
        children = [get_item(course_id, "video", item_id)
                    for item_id in _get_item_id_list(vertical.children, param['category'])]
        now = datetime.now(UTC)
        children = filter(lambda x: x and x.start < now, children)

        result = {
            # TODO: Select the other serializers
            "children": VideoSerializer(course_id, children, many=True).data
        }
        return Response(result)
Пример #6
0
def _get_children(course_id, children, category, now):
    result = []

    items = [get_item(course_id, category, item_id)
             for item_id in _get_item_id_list(children, category)]
    items = filter(lambda x: x and x.start < now, items)

    for item in items:
        data = {
            "display_name": item.display_name,
            "location": str(item.location),
            "start": item.start,
            "children": item.children,
        }
        result.append(data)

    return result
Пример #7
0
    def _get_course_info(self, request, course, chapter=None, sequential=None):
        """
        Returns the course status

        edx:

        path_ids = [unicode(module.location) for module in path]
        return Response({
           "last_visited_module_id": path_ids[0],
           "last_visited_module_path": path_ids,
        })

        {
            "last_visited_module_id": "i4x://apitestorg/apitestcourse/sequential/624e6b343d5e4b319a6a8b7fe63c9262",
            "last_visited_module_path": [
                "i4x://apitestorg/apitestcourse/sequential/624e6b343d5e4b319a6a8b7fe63c9262",
                "i4x://apitestorg/apitestcourse/chapter/a9ae78343c0f47ad91159d3b9035ea9c",
                "i4x://apitestorg/apitestcourse/course/2015_3"
            ]
        }
        """
        path = self._last_visited_module_path(request, course)
        path_ids = [(module.location) for module in path]
        course_id = course.id
        chapter_id = ''
        sequential_id = ''
        chapter_location = ''
        sequential_location = ''
        result = {'course_id': _get_course_id(course_id)}
        for path_id in path_ids:
            if u'chapter' == path_id.block_type:
                chapter_id = path_id.block_id
                chapter_location = _get_location_id(path_id)
                continue
            if u'sequential' == path_id.block_type:
                sequential_id = path_id.block_id
                sequential_location =_get_location_id(path_id)
                continue
        # chapter
        if not chapter_id:
            return result

        cache_course_children_key = 'api_course_sync.course.{}.chapter'.format(course.id)
        # 如果缓存有course_children,则说明下面的mongo查chapter查到了
        course_children = cache.get(cache_course_children_key, [])
        if not course_children:
            try:
                chapter = get_item(course.id, 'chapter', chapter_id) if not chapter else chapter
                if not chapter:
                    return result
            except ItemNotFoundError:
                return result
            course_children = get_obj_children_ids(course)
            cache.set(cache_course_children_key, course_children, 60 * 60)
        chapter_position = 0 if chapter_location not in course_children else course_children.index(chapter_location)
        result['chapter_id'] = chapter_id
        result['chapter_position'] = chapter_position
        # sequential
        if sequential_id:
            try:
                cache_chapter_children_key = 'api_course_sync.course.{}.chapter.{}.sequential'.format(course.id,
                                                                                                      chapter_id)
                visit_chapter_sequentials = cache.get(cache_chapter_children_key, [])
                if not visit_chapter_sequentials:
                    chapter = get_item(course.id, 'chapter', chapter_id) if not chapter else chapter
                    sequential = get_item(course.id, 'sequential', sequential_id) if not sequential else sequential
                    if sequential:
                        visit_chapter_sequentials = get_obj_children_ids(chapter)
                        cache.set(cache_chapter_children_key, visit_chapter_sequentials, 60 * 60)

                sequential_position = 0 if sequential_location not in visit_chapter_sequentials \
                    else visit_chapter_sequentials.index(sequential_location)
                result['sequential_id'] = sequential_id
                result['sequential_position'] = sequential_position
            except ItemNotFoundError:
                raise error.Error(status=status.HTTP_404_NOT_FOUND)
        return result
Пример #8
0
    def get(self, request, course_id, format=None):
        """ Get course chapter list.
        注意:如果移动端需要的vertical_types需要video之外的东西,整个方法需要重构
        """
        if not Course.objects.filter(course_id=course_id).exists():
            return Response(status=status.HTTP_404_NOT_FOUND)

        if not CourseEnrollment.is_enrolled(request.user, course_id):
            return Response(status=status.HTTP_403_FORBIDDEN)
        user_agent = request.META.get('HTTP_USER_AGENT', '').lower()
        if 'androidtv' in user_agent:
            is_tv = True
        else:
            is_tv = False

        show_sequentials = request.GET.get('show_sequentials')
        if show_sequentials:
            if show_sequentials == '1' or show_sequentials.lower() == 'true':
                show_sequentials = True
            else:
                show_sequentials = False
        # 首先取一下缓存
        if show_sequentials:
            # 手动清除缓存的后面
            invalite_cache = request.GET.get('cache', None)
            if invalite_cache:
                cache_key_tv = 'api.course.{}.chapters_with_seq.{}'.format(course_id, True)
                cache_key = 'api.course.{}.chapters_with_seq.{}'.format(course_id, False)
                cache.delete(cache_key_tv)
                cache.delete(cache_key)

            if settings.DEBUG:
                cache_key = 'api.course.{}.chapters_with_seq.{}'.format(course_id, is_tv) + str(time.time())
            else:
                cache_key = 'api.course.{}.chapters_with_seq.{}'.format(course_id, is_tv)

            cache_result = cache.get(cache_key)
            if cache_result:
                return Response(cache_result)

        course = get_course(course_id)
        chapters = [get_item(course_id, "chapter", chapter_id)
                    for chapter_id in _get_item_id_list(course.children, "chapter")]
        now = datetime.now(UTC)
        chapters = filter(lambda x: x and x.start < now, chapters)

        if show_sequentials:
            # key sequential, value {video:0}
            seq_type_dict = defaultdict(lambda : defaultdict(int))

            # 首先查出vertical需要的block列表
            vertical_types = ['video']
            vertical_dict = {vt: set() for vt in vertical_types}
            for vtype in vertical_types:
                blocks = get_items(course_id, vtype)
                blocks = filter(lambda x: x and x.start < now, blocks)
                vtype_set = _get_vertical_set(blocks)
                vertical_dict[vtype] = vtype_set

            for chapter in chapters:
                sequentials = [get_item(course_id, "sequential", sequential_id)
                               for sequential_id in _get_item_id_list(chapter.children, "sequential")]
                sequentials = filter(lambda x: x and x.start < now, sequentials)
                chapter.sequentials = sequentials

                for sequential in sequentials:
                    verticals = [get_item(course_id, "vertical", vertical_id)
                                 for vertical_id in _get_item_id_list(sequential.children, "vertical")]
                    verticals = filter(lambda x: x and x.start < now, verticals)
                    sequential.verticals = verticals

                    # 通过之前查出的block集合
                    for vertical in verticals:
                        blocks = vertical.children
                        for block in blocks:
                            category = _get_location_category(block)
                            block_location_id = _get_location_id(block)
                            if category in vertical_dict and block_location_id in vertical_dict[category]:
                                seq_type_dict[sequential][category] += 1

            for sequential, types in seq_type_dict.iteritems():
                sequential.type = dict(types)

            chapters_array = ChapterWithSequentialSerializer(chapters, many=True).data

            if is_tv:
                cp_array = []
                for chapters_temp in chapters_array:
                    sq_array = []
                    for sq_temp in chapters_temp['sequentials']:
                        if sq_temp['type'].get('video', None):  # tv端过滤非video
                            sq_array.append(sq_temp)
                    chapters_temp['sequentials'] = sq_array
                    if chapters_temp['sequentials'] !=[]:
                        cp_array.append(chapters_temp)
                chapters_array = cp_array

            result = {
                "chapters": chapters_array,
            }
            if is_tv:
                cache.set(cache_key, result, 60 * 60 * 24 * 7)
            else:
                cache.set(cache_key, result, 60 * 60)
        else:
            result = {
                "chapters": ChapterSerializer(chapters, many=True).data
            }
        return Response(result)