def _user(self, user_id): log.info("_user: starting for userid " + pformat(user_id)) course_key = SlashSeparatedCourseKey.from_deprecated_string( self.course_id) course_block = StudentModule.objects.all().filter( student_id=user_id, course_id=course_key, max_grade__isnull=False) course_grade = [] for n in course_block: try: q = {} usage_key = n.module_state_key block_name = get_blocks(self.request, usage_key, depth='all', requested_fields=['display_name']) root = block_name['root'] display_name = block_name['blocks'][root]['display_name'] q['earned'] = n.grade q['possible'] = n.max_grade q['display_name'] = display_name q['root'] = root course_grade.append(q) except: pass return course_grade
def _assert_block_is_gated(block, is_gated, user, course, request_factory, has_upgrade_link=True): """ Asserts that a block in a specific course is gated for a specific user Arguments: block: some sort of xblock descriptor, must implement .scope_ids.usage_id is_gated (bool): if True, this user is expected to be gated from this block user (int): user course_id (CourseLocator): id of course """ checkout_link = '#' if has_upgrade_link else None for content_getter in (_get_content_from_fragment, _get_content_from_lms_index): with patch.object(ContentTypeGatingPartition, '_get_checkout_link', return_value=checkout_link): content = content_getter(block, user.id, course, request_factory) if is_gated: assert 'content-paywall' in content if has_upgrade_link: assert 'certA_1' in content else: assert 'certA_1' not in content else: assert 'content-paywall' not in content fake_request = request_factory.get('') with patch('lms.djangoapps.course_api.blocks.api.is_request_from_mobile_app', return_value=True): blocks = get_blocks(fake_request, course.location, user=user) course_api_block = blocks['blocks'][str(block.location)] if is_gated: assert 'authorization_denial_reason' in course_api_block else: assert 'authorization_denial_reason' not in course_api_block
def _course_blocks_grade(self): data = json.loads(self.request.body) data_id = data.get('data_id') course_block = StudentModule.objects.raw( "SELECT id,AVG(grade) AS moyenne,count(id) AS total,MAX(max_grade) AS max_grade,course_id,module_id FROM courseware_studentmodule WHERE course_id = %s AND max_grade IS NOT NULL AND grade <= max_grade GROUP BY module_id", [self.course_id]) course_grade = {} for n in course_block: usage_key = n.module_state_key block_view = BlocksView() try: block_name = get_blocks(self.request, usage_key, depth='all', requested_fields=['display_name']) root = block_name['root'] for z in data_id: if root in z.get('id'): if not root in course_grade: course_grade[root] = {} course_grade[root]['moyenne'] = n.moyenne course_grade[root]['total'] = n.total course_grade[root]['max_grade'] = n.max_grade course_grade[root]['course_id'] = str(n.course_id) course_grade[root]['module_id'] = str( n.module_state_key) course_grade[root]['display_name'] = block_name[ 'blocks'][root]['display_name'] course_grade[root]['vertical_name'] = z.get( 'title') except: pass return course_grade
def get_course_structure(self): blocks_overviews = [] course_usage_key = modulestore().make_course_usage_key(self.course_key) blocks = get_blocks(self.request, course_usage_key, depth='all', requested_fields=['display_name', 'children']) root = blocks['root'] try: children = blocks['blocks'][root]['children'] for z in children: q = {} child = blocks['blocks'][z] q['display_name'] = child['display_name'] q['id'] = child['id'] try: sub_section = child['children'] q['children'] = [] for s in sub_section: sub_ = blocks['blocks'][s] a = {} a['id'] = sub_['id'] a['display_name'] = sub_['display_name'] vertical = sub_['children'] try: a['children'] = [] for v in vertical: unit = blocks['blocks'][v] w = {} w['id'] = unit['id'] w['display_name'] = unit['display_name'] try: w['children'] = unit['children'] except: w['children'] = [] a['children'].append(w) except: a['children'] = [] q['children'].append(a) except: q['children'] = [] blocks_overviews.append(q) except: children = '' return blocks_overviews
def set_initial_progress(request, course_key): course_usage_key = modulestore().make_course_usage_key(course_key) root = course_usage_key.to_deprecated_string() block_fields = ['type', 'display_name', 'children'] course_struct = get_blocks(request, course_usage_key, request.user, 'all', requested_fields=block_fields) default_progress_dict = get_default_course_progress( course_struct.get('blocks', []), root) default_progress_json = json.dumps(default_progress_dict) student_course_progress = StudentCourseProgress.objects.create( student=request.user, course_id=course_key, progress_json=default_progress_json, ) return student_course_progress.progress
def handle(self, *args, **options): def get_detail(course_key, attribute): usage_key = course_key.make_usage_key('about', attribute) try: value = modulestore().get_item(usage_key).data except ItemNotFoundError: value = None return value def iso_date(thing): if isinstance(thing, datetime.datetime): return thing.isoformat() return thing exclusion_list = [] inclusion_list = [] if options['exclude_file']: try: with open(options['exclude_file'],'rb') as exclusion_file: data = exclusion_file.readlines() exclusion_list = [x.strip() for x in data] except IOError: raise CommandError("Could not read exclusion list from '{0}'".format(options['exclude_file'])) if options['include_file']: try: with open(options['include_file'],'rb') as inclusion_file: data = inclusion_file.readlines() inclusion_list = [x.strip() for x in data] except IOError: raise CommandError("Could not read inclusion list from '{0}'".format(options['include_file'])) store = modulestore() epoch = int(time.time()) blob = { 'epoch': epoch, 'courses': [], } # For course TOC we need a user and a request. Find the first superuser defined, # that will be our user. request_user = User.objects.filter(is_superuser=True).first() factory = RequestFactory() for course in store.get_courses(): course_id_string = course.id.to_deprecated_string() if options['single_course']: if course_id_string not in [options['single_course'].strip()]: continue elif inclusion_list: if not course_id_string in inclusion_list: continue elif exclusion_list: if course_id_string in exclusion_list: continue print "Processing {}".format(course_id_string) students = CourseEnrollment.objects.users_enrolled_in(course.id) # The method of getting a table of contents for a course is quite obtuse. # We have to go all the way to simulating a request. request = factory.get('/') request.user = request_user raw_blocks = get_blocks(request, store.make_course_usage_key(course.id), request_user, requested_fields=['id', 'type', 'display_name', 'children', 'lms_web_url']) # We got the block structure. Now we need to massage it so we get the proper jump urls without site domain. # Because on the test server the site domain is wrong. blocks = {} for block_key, block in raw_blocks['blocks'].items(): try: direct_url = '/courses/' + block.get('lms_web_url').split('/courses/')[1] except IndexError: direct_url = '' blocks[block_key] = { 'id': block.get('id', ''), 'display_name': block.get('display_name', ''), 'type': block.get('type', ''), 'children_ids': block.get('children', []), 'url': direct_url } # Then we need to recursively stitch it into a tree. # We're only interested in three layers of the hierarchy for now: 'course', 'chapter', 'sequential', 'vertical'. # Everything else is the individual blocks and problems we don't care about right now. INTERESTING_BLOCKS = ['course', 'chapter', 'sequential', 'vertical'] def _get_children(parent): children = [blocks.get(n) for n in parent['children_ids'] if blocks.get(n)] # and blocks.get(n)['type'] in INTERESTING_BLOCKS] for child in children: child['children'] = _get_children(child) parent['children'] = children del parent['children_ids'] return children block_tree = _get_children(blocks[raw_blocks['root']]) course_block = { 'id': course_id_string, 'meta_data': { 'about': { 'display_name': course.display_name, 'media': { 'course_image': course_image_url(course), } }, 'block_tree': block_tree, # Yes, I'm duplicating them for now, because the about section is shot. 'display_name': course.display_name, 'banner': course_image_url(course), 'id_org': course.org, 'id_number': course.number, 'graded': course.graded, 'hidden': course.visible_to_staff_only, 'ispublic': not (course.visible_to_staff_only or False), # course.ispublic was removed in dogwood. 'grading_policy': course.grading_policy, 'advanced_modules': course.advanced_modules, 'lowest_passing_grade': course.lowest_passing_grade, 'start': iso_date(course.start), 'advertised_start': iso_date(course.advertised_start), 'end': iso_date(course.end), 'enrollment_end': iso_date(course.enrollment_end), 'enrollment_start': iso_date(course.enrollment_start), 'has_started': course.has_started(), 'has_ended': course.has_ended(), 'overview': get_detail(course.id,'overview'), 'short_description': get_detail(course.id,'short_description'), 'pre_requisite_courses': get_detail(course.id,'pre_requisite_courses'), 'video': get_detail(course.id,'video'), }, 'students': [x.username for x in students], 'global_anonymous_id': { x.username:anonymous_id_for_user(x, None) for x in students }, 'local_anonymous_id': { x.username:anonymous_id_for_user(x, course.id) for x in students }, } if not options['meta_only']: blob['grading_data_epoch'] = epoch course_block['grading_data'] = [] # Grab grades for all students that have ever had anything to do with the course. graded_students = User.objects.filter(pk__in=CourseEnrollment.objects.filter(course_id=course.id).values_list('user',flat=True)) print "{0} graded students in course {1}".format(graded_students.count(),course_id_string) if graded_students.count(): for student, gradeset, error_message \ in iterate_grades_for(course.id, graded_students): if gradeset: course_block['grading_data'].append({ 'username': student.username, 'grades': gradeset, }) else: print error_message blob['courses'].append(course_block) if options['output']: # Ensure the dump is atomic. with tempfile.NamedTemporaryFile('w', dir=os.path.dirname(options['output']), delete=False) as output_file: json.dump(blob, output_file, default=json_util.default) tempname = output_file.name os.rename(tempname, options['output']) else: print "Blob output:" print json.dumps(blob, indent=2, ensure_ascii=False, default=json_util.default)
def get_titles(self): log.info("get_titles: Starting to get titles") if self.course_key is None: self.course_key = SlashSeparatedCourseKey.from_deprecated_string( self.course_id) #get all course structure course_usage_key = modulestore().make_course_usage_key(self.course_key) blocks = get_blocks(self.request, course_usage_key, depth='all', requested_fields=['display_name', 'children']) _root = blocks['root'] blocks_overviews = [] log.info("get_titles: Got course structure") #return unit title and component root try: children = blocks['blocks'][_root]['children'] for z in children: child = blocks['blocks'][z] try: sub_section = child['children'] for s in sub_section: sub_ = blocks['blocks'][s] vertical = sub_['children'] try: for v in vertical: unit = blocks['blocks'][v] w = {} w['id'] = unit['id'] w['display_name'] = unit['display_name'] try: w['children'] = unit['children'] except: pass blocks_overviews.append(w) except: pass except: pass except: pass log.info("get_titles: Got unit titles and component root") ## GET ALL SCORED XBLOCKS FOR WHICH THERE EXISTS AT LEAST ONE ENTRY IN STUDENTMODULE studentmodule = StudentModule.objects.raw( "SELECT id,course_id,module_id FROM courseware_studentmodule WHERE course_id = %s AND max_grade IS NOT NULL AND grade <= max_grade GROUP BY module_id ORDER BY created", [self.course_id]) title = [] for n in studentmodule: try: usage_key = n.module_state_key _current = get_blocks(self.request, usage_key, depth='all', requested_fields=['display_name']) root = _current['root'] unit_name = '' for over in blocks_overviews: if str(root) in over.get('children'): unit_name = over.get('display_name') q = { "title": _current['blocks'][root]['display_name'], "root": root, 'unit': unit_name } title.append(q) except: pass log.info("get_titles: All titles fetched") return title
def _dashboard_username(self): context = { "course_id": self.course_id, "username": self.username, "user_id": '', "course_grade": [], "user_info": '', } try: # get users info users = User.objects.get(username=self.username) # get user id user_id = users.id # get course_key from url's param course_key = SlashSeparatedCourseKey.from_deprecated_string( self.course_id) # get course from course_key course = get_course_by_id(course_key) # get all courses block of the site course_block = StudentModule.objects.all().filter( student_id=user_id, course_id=course_key, max_grade__isnull=False) # var of grades / course_structure course_grade = [] # get course_users_info course_user_info = CourseGradeFactory().create(users, course) # user info responses user_info = [{ 'Grade': str(course_user_info.percent * 100) + '%' }, { 'First_name': users.first_name }, { 'Last_name': users.last_name }, { 'Email': users.email }] for n in course_block: q = {} usage_key = n.module_state_key block_view = BlocksView() block_name = get_blocks(self.request, usage_key, depth='all', requested_fields=['display_name']) root = block_name['root'] display_name = block_name['blocks'][root]['display_name'] q['earned'] = n.grade q['possible'] = n.max_grade q['display_name'] = display_name q['root'] = root course_grade.append(q) context["user_id"] = user_id context["course_grade"] = course_grade context["user_info"] = user_info except: pass return context
def update_course_progress(request, course_key, module_type, usage_keys): """ Description: To calculate and update the course progress for specified student and course. Arguments: request: HTTPRequest obj course_key: SlashSeparatedCourseKey instance, identifying the course instance: progress affecting xblock module module_type: type of the xblock i.e. problem, video etc. usage_keys: list of usage key instances Notes: For each Block traversed, the following is verified and the block is excluded when not accessible by the user. 1. Block is not visible_to_staff_only 2. The Block has been released 3. The cohort affiliation of the Block matches the requested user's cohort Author: Naresh Makwana """ # Initialization student = request.user course_struct = {} root = None course_progress = {} chapter_wise_progress = OrderedDict() # Get course structure course_usage_key = modulestore().make_course_usage_key(course_key) root = course_usage_key.to_deprecated_string() block_fields = ['type', 'display_name', 'children'] course_struct = get_blocks(request, course_usage_key, request.user, 'all', requested_fields=block_fields) # get course progress object try: student_course_progress = StudentCourseProgress.objects.get(student=student.id, course_id=course_key) except StudentCourseProgress.DoesNotExist: default_progress_dict = get_default_course_progress( course_struct.get('blocks', []), root ) default_progress_json = json.dumps(default_progress_dict) student_course_progress = StudentCourseProgress.objects.create( student=student, course_id=course_key, progress_json=default_progress_json, ) # Get course progress dict progress = student_course_progress.progress # To have proper sync with blocks and stored progress new_progress = {} default_progress_dict = get_default_course_progress( course_struct.get('blocks', []), root ) for default_block_id, default_block in default_progress_dict.items(): progress_block = progress.get(default_block_id, {}) stored_progress = progress_block.get('progress', 0) default_block.update({'progress': stored_progress}) new_progress.update({default_block_id: default_block}) progress = new_progress # increase progress if attempted or graded and not already updated updated_units = [] for usage_key in usage_keys: usage_id = usage_key.to_deprecated_string() current_progress = progress.get(usage_id, {}).get('progress') if current_progress != 100: progress[usage_id]['progress'] = 100 updated_units.append(progress[usage_id]['parent']) # update unit progress if updated_units: update_unit_progress(progress, list(set(updated_units)) ) student_course_progress.progress_json = json.dumps(progress) student_course_progress.overall_progress = progress[root]['progress'] student_course_progress.save()
def handle(self, *args, **options): def get_detail(course_key, attribute): usage_key = course_key.make_usage_key('about', attribute) try: value = modulestore().get_item(usage_key).data except ItemNotFoundError: value = None return value def iso_date(thing): if isinstance(thing, datetime.datetime): return thing.isoformat() return thing exclusion_list = [] inclusion_list = [] if options['exclude_file']: try: with open(options['exclude_file'], 'rb') as exclusion_file: data = exclusion_file.readlines() exclusion_list = [x.strip() for x in data] except IOError: raise CommandError( "Could not read exclusion list from '{0}'".format( options['exclude_file'])) if options['include_file']: try: with open(options['include_file'], 'rb') as inclusion_file: data = inclusion_file.readlines() inclusion_list = [x.strip() for x in data] except IOError: raise CommandError( "Could not read inclusion list from '{0}'".format( options['include_file'])) store = modulestore() epoch = int(time.time()) blob = { 'epoch': epoch, 'courses': [], } # For course TOC we need a user and a request. Find the first superuser defined, # that will be our user. request_user = User.objects.filter(is_superuser=True).first() factory = RequestFactory() for course in store.get_courses(): course_id_string = course.id.to_deprecated_string() if options['single_course']: if course_id_string not in [options['single_course'].strip()]: continue elif inclusion_list: if not course_id_string in inclusion_list: continue elif exclusion_list: if course_id_string in exclusion_list: continue print "Processing {}".format(course_id_string) students = CourseEnrollment.objects.users_enrolled_in(course.id) # The method of getting a table of contents for a course is quite obtuse. # We have to go all the way to simulating a request. request = factory.get('/') request.user = request_user raw_blocks = get_blocks(request, store.make_course_usage_key(course.id), request_user, requested_fields=[ 'id', 'type', 'display_name', 'children', 'lms_web_url' ]) # We got the block structure. Now we need to massage it so we get the proper jump urls without site domain. # Because on the test server the site domain is wrong. blocks = {} for block_key, block in raw_blocks['blocks'].items(): try: direct_url = '/courses/' + block.get('lms_web_url').split( '/courses/')[1] except IndexError: direct_url = '' blocks[block_key] = { 'id': block.get('id', ''), 'display_name': block.get('display_name', ''), 'type': block.get('type', ''), 'children_ids': block.get('children', []), 'url': direct_url } # Then we need to recursively stitch it into a tree. # We're only interested in three layers of the hierarchy for now: 'course', 'chapter', 'sequential', 'vertical'. # Everything else is the individual blocks and problems we don't care about right now. INTERESTING_BLOCKS = [ 'course', 'chapter', 'sequential', 'vertical' ] def _get_children(parent): children = [ blocks.get(n) for n in parent['children_ids'] if blocks.get(n) ] # and blocks.get(n)['type'] in INTERESTING_BLOCKS] for child in children: child['children'] = _get_children(child) parent['children'] = children del parent['children_ids'] return children block_tree = _get_children(blocks[raw_blocks['root']]) course_block = { 'id': course_id_string, 'meta_data': { 'about': { 'display_name': course.display_name, 'media': { 'course_image': course_image_url(course), } }, 'block_tree': block_tree, # Yes, I'm duplicating them for now, because the about section is shot. 'display_name': course.display_name, 'banner': course_image_url(course), 'id_org': course.org, 'id_number': course.number, 'graded': course.graded, 'hidden': course.visible_to_staff_only, 'ispublic': not (course.visible_to_staff_only or False), # course.ispublic was removed in dogwood. 'grading_policy': course.grading_policy, 'advanced_modules': course.advanced_modules, 'lowest_passing_grade': course.lowest_passing_grade, 'start': iso_date(course.start), 'advertised_start': iso_date(course.advertised_start), 'end': iso_date(course.end), 'enrollment_end': iso_date(course.enrollment_end), 'enrollment_start': iso_date(course.enrollment_start), 'has_started': course.has_started(), 'has_ended': course.has_ended(), 'overview': get_detail(course.id, 'overview'), 'short_description': get_detail(course.id, 'short_description'), 'pre_requisite_courses': get_detail(course.id, 'pre_requisite_courses'), 'video': get_detail(course.id, 'video'), }, 'students': [x.username for x in students], 'global_anonymous_id': {x.username: anonymous_id_for_user(x, None) for x in students}, 'local_anonymous_id': { x.username: anonymous_id_for_user(x, course.id) for x in students }, } if not options['meta_only']: blob['grading_data_epoch'] = epoch course_block['grading_data'] = [] # Grab grades for all students that have ever had anything to do with the course. graded_students = User.objects.filter( pk__in=CourseEnrollment.objects.filter( course_id=course.id).values_list('user', flat=True)) print "{0} graded students in course {1}".format( graded_students.count(), course_id_string) if graded_students.count(): for student, gradeset, error_message \ in iterate_grades_for(course.id, graded_students): if gradeset: course_block['grading_data'].append({ 'username': student.username, 'grades': gradeset, }) else: print error_message blob['courses'].append(course_block) if options['output']: # Ensure the dump is atomic. with tempfile.NamedTemporaryFile('w', dir=os.path.dirname( options['output']), delete=False) as output_file: json.dump(blob, output_file, default=json_util.default) tempname = output_file.name os.rename(tempname, options['output']) else: print "Blob output:" print json.dumps(blob, indent=2, ensure_ascii=False, default=json_util.default)