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