def student_process(request, course_id, user_id): try: __, course = _get_locator_and_course(course_id, 'draft', None, course_id.split('.')[-1], request.user, depth=None) except: raise Http404('没有找到对应课程!') student = User.objects.prefetch_related("groups").get(id=user_id) courseware_summary = grades.progress_summary(student, request, course) grade_summary = grade.grade(student, request, course) if courseware_summary is None: raise Http404 context = { 'course': course, 'courseware_summary': courseware_summary, 'grade_summary': grade_summary, 'student': student, } return JsonResponse(context)
def get_student_course_stats_base(request,course, type="grades"): """ Called by get_student_course_stats and get_student_problem_stats Gets a list of users in a course, and then computes grades for them request - a mock request (using RequestDict) course - a string course id type - whether to get student weighted grades or unweighted grades. If "grades" will get weighted """ fs, db = common.get_db_and_fs_cron(common.student_course_stats_stub) course_obj = get_course_with_access(request.user, course, 'load', depth=None) users_in_course = StudentModule.objects.filter(course_id=course).values('student').distinct() users_in_course_ids = [u['student'] for u in users_in_course] log.debug("Users in course count: {0}".format(len(users_in_course_ids))) courseware_summaries = [] for i in xrange(0,len(users_in_course_ids)): try: user = users_in_course_ids[i] current_task.update_state(state='PROGRESS', meta={'current': i, 'total': len(users_in_course_ids)}) student = User.objects.using('remote').prefetch_related("groups").get(id=int(user)) model_data_cache = None if type=="grades": grade_summary = grades.grade(student, request, course_obj, model_data_cache) else: grade_summary = grades.progress_summary(student, request, course_obj, model_data_cache) courseware_summaries.append(grade_summary) except: log.exception("Could not generate data for {0}".format(users_in_course_ids[i])) return courseware_summaries, users_in_course_ids
def report(self): """Report course grade.""" students = self._get_students() print "\nFetching course data for {0}".format(self.course_id) course = courses.get_course_by_id(self.course_id) request = self._create_request() total = {'users': 0, 'pass': 0, 'notpass': 0} print "Summary Report: Course Name [{0}]".format( course.display_name.encode('utf_8')) for student in students.iterator(): request.user = student total['users'] += 1 certs = GeneratedCertificate.objects.filter( user=student, course_id=self.course_id) for cert in certs.iterator(): grade = grades.grade(cert.user, request, course) summary = grades.progress_summary(student, request, course) self._report_summary(summary) self._add_total(cert.user, grade, total) self._report_total(total)
def handle(self, *args, **options): course_ids = options.get('course_ids') user_ids = options.get('user_ids') # Get the list of courses from the system courses = modulestore().get_courses() # If one or more courses were specified by the caller, just use those ones... if course_ids is not None: filtered_courses = [] for course in courses: if unicode(course.id) in course_ids.split(','): filtered_courses.append(course) courses = filtered_courses for course in courses: users = CourseEnrollment.objects.users_enrolled_in(course.id) # If one or more users were specified by the caller, just use those ones... if user_ids is not None: filtered_users = [] for user in users: if str(user.id) in user_ids.split(','): filtered_users.append(user) users = filtered_users # For each user... for user in users: grade_data = grades.grade(user, course) grade = grade_data['percent'] grading_policy = course.grading_policy proforma_grade = grades.calculate_proforma_grade(grade_data, grading_policy) progress_summary = grades.progress_summary(user, course) try: gradebook_entry = StudentGradebook.objects.get(user=user, course_id=course.id) if (gradebook_entry.grade != grade or gradebook_entry.proforma_grade != proforma_grade or gradebook_entry.progress_summary != progress_summary or gradebook_entry.grade_summary != grade_data or gradebook_entry.grading_policy != grading_policy): gradebook_entry.grade = grade gradebook_entry.proforma_grade = proforma_grade gradebook_entry.progress_summary = json.dumps(progress_summary, cls=EdxJSONEncoder) gradebook_entry.grade_summary = json.dumps(grade_data, cls=EdxJSONEncoder) gradebook_entry.grading_policy = json.dumps(grading_policy, cls=EdxJSONEncoder) gradebook_entry.save() except StudentGradebook.DoesNotExist: StudentGradebook.objects.create( user=user, course_id=course.id, grade=grade, proforma_grade=proforma_grade, progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder), grade_summary=json.dumps(grade_data, cls=EdxJSONEncoder), grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder) ) log_msg = 'Gradebook entry created -- Course: {}, User: {} (grade: {}, proforma_grade: {})'.format(course.id, user.id, grade, proforma_grade) print log_msg log.info(log_msg)
def _progress(request, course_key, student_id): """ Unwrapped version of "progress". User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course = get_course_with_access(request.user, 'load', course_key, depth=None, check_if_enrolled=True) # check to see if there is a required survey that must be taken before # the user can access the course. if survey.utils.must_answer_survey(course, request.user): return redirect(reverse('course_survey', args=[unicode(course.id)])) staff_access = has_access(request.user, 'staff', course) if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) courseware_summary = grades.progress_summary(student, request, course) studio_url = get_studio_url(course, 'settings/grading') grade_summary = grades.grade(student, request, course) if courseware_summary is None: #This means the student didn't have access to the course (which the instructor requested) raise Http404 context = { 'course': course, 'courseware_summary': courseware_summary, 'studio_url': studio_url, 'grade_summary': grade_summary, 'staff_access': staff_access, 'student': student, 'reverifications': fetch_reverify_banner_info(request, course_key) } with grades.manual_transaction(): response = render_to_response('courseware/progress.html', context) return response
def render_accordion(request, course, chapter, section, model_data_cache): """ Draws navigation bar. Takes current position in accordion as parameter. If chapter and section are '' or None, renders a default accordion. course, chapter, and section are the url_names. Returns the html string """ staff_access = has_access(request.user, course, "staff") # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). course_id = course.id student_id = None if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) student = User.objects.prefetch_related("groups").get(id=student.id) model_data_cache = ModelDataCache.cache_for_descriptor_descendents(course_id, student, course, depth=None) courseware_summary = grades.progress_summary(student, request, course, model_data_cache) print("<-------------") print(courseware_summary) print("------------->") # grab the table of contents user = User.objects.prefetch_related("groups").get(id=request.user.id) request.user = user # keep just one instance of User toc = toc_for_course(user, request, course, chapter, section, model_data_cache) context = dict( [ ("toc", toc), ("course_id", course.id), ("csrf", csrf(request)["csrf_token"]), ("show_timezone", course.show_timezone), ("courseware_summary", courseware_summary), ] + template_imports.items() ) return render_to_string("courseware/accordion.html", context)
def get_progress_summary(self): """ Return progress summary structure for current user and course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. """ return grades.progress_summary(self.student_user, self.course)
def get_progress_summary(self): '''return progress summary structure for current user and course''' model_data_cache = ModelDataCache.cache_for_descriptor_descendents( self.course.id, self.student_user, self.course) fake_request = self.factory.get( reverse('progress', kwargs={'course_id': self.course.id})) progress_summary = grades.progress_summary(self.student_user, fake_request, self.course, model_data_cache) return progress_summary
def get_progress_summary(self): '''return progress summary structure for current user and course''' model_data_cache = ModelDataCache.cache_for_descriptor_descendents( self.course.id, self.student_user, self.course) fake_request = self.factory.get(reverse('progress', kwargs={'course_id': self.course.id})) progress_summary = grades.progress_summary(self.student_user, fake_request, self.course, model_data_cache) return progress_summary
def _progress(request, course_id, student_id): """ Unwrapped version of "progress". User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course = get_course_with_access(request.user, course_id, 'load', depth=None) staff_access = has_access(request.user, course, 'staff') if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) courseware_summary = grades.progress_summary(student, request, course) grade_summary = grades.grade(student, request, course) if courseware_summary is None: #This means the student didn't have access to the course (which the instructor requested) raise Http404 context = { 'course': course, 'courseware_summary': courseware_summary, 'grade_summary': grade_summary, 'staff_access': staff_access, 'student': student, } with grades.manual_transaction(): response = render_to_response('courseware/progress.html', context) return response
def _progress(request, course_id, student_id): """ Unwrapped version of "progress". User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course = get_course_with_access(request.user, course_id, "load", depth=None) staff_access = has_access(request.user, course, "staff") if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) courseware_summary = grades.progress_summary(student, request, course) studio_url = get_studio_url(course_id, "settings/grading") grade_summary = grades.grade(student, request, course) if courseware_summary is None: # This means the student didn't have access to the course (which the instructor requested) raise Http404 context = { "course": course, "courseware_summary": courseware_summary, "studio_url": studio_url, "grade_summary": grade_summary, "staff_access": staff_access, "student": student, "reverifications": fetch_reverify_banner_info(request, course_id), } with grades.manual_transaction(): response = render_to_response("courseware/progress.html", context) return response
def get_progress_summary(self): """ Return progress summary structure for current user and course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. """ fake_request = self.factory.get(reverse("progress", kwargs={"course_id": self.course.id})) progress_summary = grades.progress_summary(self.student_user, fake_request, self.course) return progress_summary
def handle(self, *args, **options): course_id = options.get('course_id') course_ids = [] if course_id: course_ids.append(course_id) else: course_ids = StudentGradebook.objects.filter( grade_summary='').values_list('course_id', flat=True) for course_id in course_ids: course_key = CourseKey.from_string(course_id) users = CourseEnrollment.objects.users_enrolled_in(course_key) course = modulestore().get_course(course_key, depth=None) if course: # For each user... for user in users: request = RequestMockWithoutMiddleware().get('/') request.user = user grade_data = grades.grade(user, course) grade = grade_data['percent'] grading_policy = course.grading_policy proforma_grade = grades.calculate_proforma_grade( grade_data, grading_policy) progress_summary = grades.progress_summary(user, course) try: gradebook_entry = StudentGradebook.objects.get( user=user, course_id=course.id) if not gradebook_entry.grade_summary: gradebook_entry.grade = grade gradebook_entry.proforma_grade = proforma_grade gradebook_entry.progress_summary = json.dumps( progress_summary, cls=EdxJSONEncoder) gradebook_entry.grade_summary = json.dumps( grade_data, cls=EdxJSONEncoder) gradebook_entry.grading_policy = json.dumps( grading_policy, cls=EdxJSONEncoder) gradebook_entry.save() except StudentGradebook.DoesNotExist: pass log_msg = 'Gradebook entry created -- Course: {}, User: {} (grade: {}, proforma_grade: {})'.format( course.id, user.id, grade, proforma_grade) log.info(log_msg)
def get_progress_summary(self): """ Return progress summary structure for current user and course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. """ fake_request = self.factory.get( reverse('progress', kwargs={'course_id': self.course.id})) progress_summary = grades.progress_summary(self.student_user, fake_request, self.course) return progress_summary
def progress(request, course_id, student_id=None): """ User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course = get_course_with_access(request.user, course_id, 'load', depth=None) staff_access = has_access(request.user, course, 'staff') if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, student, course, depth=None) courseware_summary = grades.progress_summary(student, request, course, field_data_cache) grade_summary = grades.grade(student, request, course, field_data_cache) if courseware_summary is None: #This means the student didn't have access to the course (which the instructor requested) raise Http404 context = {'course': course, 'courseware_summary': courseware_summary, 'grade_summary': grade_summary, 'staff_access': staff_access, 'student': student, } context.update() return render_to_response('courseware/progress.html', context)
def get_student_course_stats_base(request, course, type="grades"): """ Called by get_student_course_stats and get_student_problem_stats Gets a list of users in a course, and then computes grades for them request - a mock request (using RequestDict) course - a string course id type - whether to get student weighted grades or unweighted grades. If "grades" will get weighted """ fs, db = common.get_db_and_fs_cron(common.student_course_stats_stub) course_obj = get_course_with_access(request.user, course, 'load', depth=None) users_in_course = StudentModule.objects.filter( course_id=course).values('student').distinct() users_in_course_ids = [u['student'] for u in users_in_course] log.debug("Users in course count: {0}".format(len(users_in_course_ids))) courseware_summaries = [] for i in xrange(0, len(users_in_course_ids)): try: user = users_in_course_ids[i] current_task.update_state(state='PROGRESS', meta={ 'current': i, 'total': len(users_in_course_ids) }) student = User.objects.using('remote').prefetch_related( "groups").get(id=int(user)) model_data_cache = None if type == "grades": grade_summary = grades.grade(student, request, course_obj, model_data_cache) else: grade_summary = grades.progress_summary( student, request, course_obj, model_data_cache) courseware_summaries.append(grade_summary) except: log.exception("Could not generate data for {0}".format( users_in_course_ids[i])) return courseware_summaries, users_in_course_ids
def progress(request, course_id, student_id): """ Unwrapped version of "progress". courseware_summary User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) course = get_course_with_access(request.user, 'load', course_key, depth=None) # course = get_course_with_access(request.user, course_id, 'load', depth=None) staff_access = has_access(request.user, 'staff', course) if not staff_access: raise Http404 if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) try: courseware_summary = grades.progress_summary(student, request, course) except: courseware_summary = None return courseware_summary
def render_accordion(request, course, chapter, section, field_data_cache): """ Draws navigation bar. Takes current position in accordion as parameter. If chapter and section are '' or None, renders a default accordion. course, chapter, and section are the url_names. Returns the html string """ # grab the table of contents staff_access = has_access(request.user, course, 'staff') student_id = None if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) student = User.objects.prefetch_related("groups").get(id=student.id) user = User.objects.prefetch_related("groups").get(id=request.user.id) request.user = user # keep just one instance of User toc = toc_for_course(user, request, course, chapter, section, field_data_cache) is_demo = UserProfile.objects.get(user=request.user).is_demo courseware_summary = grades.progress_summary(student, request, course) context = dict([('toc', toc), ('course_id', course.id), ('is_demo', is_demo), ('csrf', csrf(request)['csrf_token']), ('courseware_summary', courseware_summary), ('due_date_display_format', course.due_date_display_format)] + template_imports.items()) return render_to_string('courseware/accordion.html', context)
def get_progress_summary(self): """ Return progress summary structure for current user and course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. """ model_data_cache = ModelDataCache.cache_for_descriptor_descendents( self.course.id, self.student_user, self.course) fake_request = self.factory.get(reverse('progress', kwargs={'course_id': self.course.id})) progress_summary = grades.progress_summary(self.student_user, fake_request, self.course, model_data_cache) return progress_summary
def on_score_changed(sender, **kwargs): """ Listens for a 'score_changed' signal and when observed recalculates the specified user's gradebook entry """ from courseware.views import get_course user = kwargs['user'] course_key = kwargs['course_key'] course_descriptor = get_course(course_key, depth=None) request = RequestMockWithoutMiddleware().get('/') request.user = user progress_summary = grades.progress_summary(user, request, course_descriptor, locators_as_strings=True) grade_summary = grades.grade(user, request, course_descriptor) grading_policy = course_descriptor.grading_policy grade = grade_summary['percent'] proforma_grade = grades.calculate_proforma_grade(grade_summary, grading_policy) try: gradebook_entry = StudentGradebook.objects.get(user=user, course_id=course_key) if gradebook_entry.grade != grade: gradebook_entry.grade = grade gradebook_entry.proforma_grade = proforma_grade gradebook_entry.progress_summary = json.dumps(progress_summary, cls=EdxJSONEncoder) gradebook_entry.grade_summary = json.dumps(grade_summary, cls=EdxJSONEncoder) gradebook_entry.grading_policy = json.dumps(grading_policy, cls=EdxJSONEncoder) gradebook_entry.save() except StudentGradebook.DoesNotExist: StudentGradebook.objects.create( user=user, course_id=course_key, grade=grade, proforma_grade=proforma_grade, progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder), grade_summary=json.dumps(grade_summary, cls=EdxJSONEncoder), grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder) )
def student_process(request, course_id, user_id): try: __, course = _get_locator_and_course( course_id, 'draft', None, course_id.split('.')[-1], request.user, depth=None ) except: raise Http404('没有找到对应课程!') student = User.objects.prefetch_related("groups").get(id=user_id) courseware_summary = grades.progress_summary(student, request, course) grade_summary = grade.grade(student, request, course) if courseware_summary is None: raise Http404 context = { 'course': course, 'courseware_summary': courseware_summary, 'grade_summary': grade_summary, 'student': student, } return JsonResponse(context)
def prepare_sections_with_grade(request, course): ''' Create sections with grade details. Return format: { 'sections': [ { 'display_name': name, # in case of cohorts or any other accessibility settings 'hidden': hidden, 'url_name': url_name, 'units': UNITS, 'rank': rank, 'badge': bagde status, 'points': grade points, 'podium': podium status, 'week': section_index + 1, }, ], } where UNITS is a list [ { 'display_name': name, 'position': unit position in section, 'css_class': css class, } , ... ] sections with name 'hidden' are skipped. NOTE: assumes that if we got this far, user has access to course. Returns [] if this is not the case. ''' # Set the student to request user student = request.user # Get the field data cache field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, student, course, depth=2, ) # Get the course module with modulestore().bulk_operations(course.id): course_module = get_module_for_descriptor( student, request, course, field_data_cache, course.id, course=course ) if course_module is None: return [] # Get the field data cache staff_user = User.objects.filter(is_staff=1)[0] staff_field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, staff_user, course, depth=2, ) # Get the course module with modulestore().bulk_operations(course.id): staff_course_module = get_module_for_descriptor( staff_user, request, course, staff_field_data_cache, course.id, course=course ) # staff accessible chapters staff_chapters = staff_course_module.get_display_items() # find the passing grade for the course nonzero_cutoffs = [cutoff for cutoff in course.grade_cutoffs.values() if cutoff > 0] success_cutoff = min(nonzero_cutoffs) if nonzero_cutoffs else 0 # find the course progress progress = get_course_progress(student, course.id) # prepare a list of discussions participated by user discussions_participated = get_discussions_participated( request, course.id.to_deprecated_string(), student.id ) # get courseware summary with outer_atomic(): field_data_cache = grades.field_data_cache_for_grading(course, student) scores_client = ScoresClient.from_field_data_cache(field_data_cache) courseware_summary = grades.progress_summary( student, request, course, field_data_cache=field_data_cache, scores_client=scores_client ) section_grades = {} for section in courseware_summary: earned = 0 total = 0 for sub_section in section['sections']: earned += sub_section['section_total'].earned total += sub_section['section_total'].possible section_score = earned / total if earned > 0 and total > 0 else 0 section_grades[section['url_name']] = { 'earned': earned, 'total': total, 'css_class': ('text-red', 'text-green')[int(section_score >= 0.6)] if total > 0 else '' } # Check for content which needs to be completed # before the rest of the content is made available required_content = milestones_helpers.get_required_content(course, student) # Check for gated content gated_content = gating_api.get_gated_content(course, student) # The user may not actually have to complete the entrance exam, if one is required if not user_must_complete_entrance_exam(request, student, course): required_content = [content for content in required_content if not content == course.entrance_exam_id] # define inner function def create_module(descriptor): '''creates an XModule instance given a descriptor''' return get_module_for_descriptor( student, request, descriptor, field_data_cache, course.id, course=course ) with outer_atomic(): submissions_scores = sub_api.get_scores( course.id.to_deprecated_string(), anonymous_id_for_user(student, course.id) ) max_scores_cache = grades.MaxScoresCache.create_for_course(course) max_scores_cache.fetch_from_remote(field_data_cache.scorable_locations) sections = list() student_chapters = course_module.get_display_items() urlname_chapters = {} for student_chap in student_chapters: urlname_chapters.update({student_chap.url_name:student_chap}) final_chapters = OrderedDict() for chapter_index, chapter in enumerate(staff_chapters): fin_chap = urlname_chapters.get(chapter.url_name) if fin_chap: final_chapters.update({str(chapter_index+1):{'hidden': False, 'chapter':fin_chap}}) else: final_chapters.update({str(chapter_index+1):{'hidden':True}}) for section_index, chapter_info in final_chapters.items(): # Mark as hidden and Skip the current chapter if a hide flag is tripped if chapter_info['hidden']: sections.append({ 'hidden': True, 'week': "WEEK {week}: ".format(week=section_index), 'points': { 'total': 0, 'earned': 0, 'css_class': 'text-disabled' }, }) continue chapter = chapter_info['chapter'] # get the points section_points = section_grades.get(chapter.url_name, {}) units = list() for sequential in chapter.get_display_items(): # Set hidden status of the sequential if it is gated/hidden from the user hidden = ( gated_content and unicode(sequential.location) in gated_content or sequential.hide_from_toc ) if hidden: continue for index, unit in enumerate(sequential.get_display_items()): css_class = 'dark-gray' if unit.graded: total_excercises = 0 attempted_excercises = 0 unit_max_score = 0 unit_score = 0 for component in unit.get_display_items(): if component.category == 'problem': if component.graded: total_excercises += 1 attempted_excercises += is_attempted_internal( str(component.location), progress ) (correct, total) = grades.get_score( student, component, create_module, scores_client, submissions_scores, max_scores_cache, ) unit_max_score += total unit_score += correct if total_excercises: css_class = 'blue' if attempted_excercises == total_excercises: css_class = 'green' if unit_max_score and unit_score / unit_max_score < success_cutoff: css_class = 'red' position = index + 1 # For jumping to the unit directly unit_context = { 'display_name': unit.display_name_with_default_escaped, 'position': position, 'css_class': css_class, 'courseware_url': reverse( 'courseware_position', args=[ course.id, chapter.url_name, sequential.url_name, position ] ) } units.append(unit_context) competency = None if int(section_points.get('total')): competency = int(section_points.get('earned')) == int(section_points.get('total')) section_context = { 'display_name': chapter.display_name_with_default_escaped, 'url_name': chapter.url_name, 'hidden': False, 'rank': 1, 'competency': competency, 'points': { 'total': int(section_points.get('total')), 'earned': int(section_points.get('earned')), 'css_class': section_points.get('css_class') }, 'participation': discussions_participated.get(chapter.url_name), 'units': units, 'week': "WEEK {week}: ".format(week=section_index), } sections.append(section_context) return sections
def _progress(request, course_key, student_id): """ Unwrapped version of "progress". User progress. We show the grade bar and every problem score. Course staff are allowed to see the progress of students in their class. """ course = get_course_with_access(request.user, 'load', course_key, depth=None) staff_access = has_access(request.user, 'staff', course) if student_id is None or student_id == request.user.id: # always allowed to see your own profile student = request.user else: # Requesting access to a different student's profile if not staff_access: raise Http404 student = User.objects.get(id=int(student_id)) # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) courseware_summary = grades.progress_summary(student, request, course) if courseware_summary is None: #This means the student didn't have access to the course (which the instructor requested) raise Http404 else: i=0 while i < len(courseware_summary): need = NeedThread(request.user, course) if need: print "Precisa de thread" mythread = CadVersao(courseware_summary[i]['url_name'], request.user) mythread.start() mythread.join() imprimir = mythread.getResult() else: print "Nao precisa de thread" imprimir = VerABprint(courseware_summary[i]['url_name'], request.user) if imprimir == False: del courseware_summary[i] else: i += 1 studio_url = get_studio_url(course_key, 'settings/grading') grade_summary = grades.grade(student, request, course) context = { 'course': course, 'courseware_summary': courseware_summary, 'studio_url': studio_url, 'grade_summary': grade_summary, 'staff_access': staff_access, 'student': student, 'reverifications': fetch_reverify_banner_info(request, course_key) } with grades.manual_transaction(): response = render_to_response('courseware/progress.html', context) return response
def index(request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, redirects to user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: - request : HTTP request - course_id : course id (str: ORG/course/URL_NAME) - chapter : chapter url_name (str) - section : section url_name (str) - position : position in module, eg of <sequential> module (str) Returns: - HTTPresponse """ user = User.objects.prefetch_related("groups").get(id=request.user.id) request.user = user # keep just one instance of User course = get_course_with_access(user, course_id, "load", depth=2) staff_access = has_access(user, course, "staff") registered = registered_for_course(course, user) if not registered: # TODO (vshnayder): do course instructors need to be registered to see course? log.debug("User %s tried to view course %s but is not enrolled" % (user, course.location.url())) return redirect(reverse("about_course", args=[course.id])) masq = setup_masquerade(request, staff_access) try: model_data_cache = ModelDataCache.cache_for_descriptor_descendents(course.id, user, course, depth=2) course_module = get_module_for_descriptor(user, request, course, model_data_cache, course.id) if course_module is None: log.warning( "If you see this, something went wrong: if we got this" " far, should have gotten a course module for this user" ) return redirect(reverse("about_course", args=[course.id])) if chapter is None: return redirect_to_course_position(course_module) # check course constraints courses = modulestore().get_items(["i4x", None, None, "course", None]) def course_filter(course): return ( has_access(user, course, "see_exists") # TODO remove this condition when templates purged from db and course.location.course != "templates" and course.location.org != "" and course.location.course != "" and course.location.name != "" ) courses = filter(course_filter, courses) courses_by_id = dict((course.location.url(), course) for course in courses) if not is_item_unlocked(course.unlock_term, courses_by_id, lambda course: grade(user, request, course)): raise Http404 context = { "csrf": csrf(request)["csrf_token"], "accordion": render_accordion(request, course, chapter, section, model_data_cache), "COURSE_TITLE": course.display_name_with_default, "course": course, "init": "", "content": "", "staff_access": staff_access, "masquerade": masq, "xqa_server": settings.MITX_FEATURES.get("USE_XQA_SERVER", "http://*****:*****@content-qa.mitx.mit.edu/xqa"), } # Only show the chat if it's enabled by the course and in the # settings. show_chat = course.show_chat and settings.MITX_FEATURES["ENABLE_CHAT"] if show_chat: context["chat"] = chat_settings(course, user) # If we couldn't load the chat settings, then don't show # the widget in the courseware. if context["chat"] is None: show_chat = False context["show_chat"] = show_chat chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter) if chapter_descriptor is not None: save_child_position(course_module, chapter) else: raise Http404("No chapter descriptor found with name {}".format(chapter)) chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter) if chapter_module is None: # User may be trying to access a chapter that isn't live yet if masq == "student": # if staff is masquerading as student be kinder, don't 404 log.debug("staff masq as student: no chapter %s" % chapter) return redirect(reverse("courseware", args=[course.id])) raise Http404 if section is not None: section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section) if section_descriptor is None: # Specifically asked-for section doesn't exist if masq == "student": # if staff is masquerading as student be kinder, don't 404 log.debug("staff masq as student: no section %s" % section) return redirect(reverse("courseware", args=[course.id])) raise Http404 # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None # which will prefetch the children more efficiently than doing a recursive load section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None) # Load all descendants of the section, because we're going to display its # html, which in general will need all of its children section_model_data_cache = ModelDataCache.cache_for_descriptor_descendents( course_id, user, section_descriptor, depth=None ) section_module = get_module( request.user, request, section_descriptor.location, section_model_data_cache, course_id, position, depth=None, ) if section_module is None: # User may be trying to be clever and access something # they don't have access to. raise Http404 model_data_cache_for_check = ModelDataCache.cache_for_descriptor_descendents( course_id, user, course, depth=None ) courseware_summary = grades.progress_summary(user, request, course, model_data_cache_for_check) is_section_unlocked = grades.return_section_by_id(section_module.url_name, courseware_summary)["unlocked"] # Save where we are in the chapter save_child_position(chapter_module, section) # check here if this section *is* a timed module. if section_module.category == "timelimit": timer_context = update_timelimit_module( user, course_id, student_module_cache, section_descriptor, section_module ) if "timer_expiration_duration" in timer_context: context.update(timer_context) else: # if there is no expiration defined, then we know the timer has expired: return HttpResponseRedirect(timer_context["time_expired_redirect_url"]) else: # check here if this page is within a course that has an active timed module running. If so, then # add in the appropriate timer information to the rendering context: context.update(check_for_active_timelimit_module(request, course_id, course)) # context['content'] = section_module.runtime.render(section_module, None, 'student_view').content if not is_section_unlocked: context["content"] = u"Раздел вам пока не доступен" else: context["content"] = section_module.runtime.render(section_module, None, "student_view").content # context['content'] = section_module.get_html() else: # section is none, so display a message prev_section = get_current_child(chapter_module) if prev_section is None: # Something went wrong -- perhaps this chapter has no sections visible to the user raise Http404 prev_section_url = reverse( "courseware_section", kwargs={ "course_id": course_id, "chapter": chapter_descriptor.url_name, "section": prev_section.url_name, }, ) context["content"] = render_to_string( "courseware/welcome-back.html", { "course": course, "chapter_module": chapter_module, "prev_section": prev_section, "prev_section_url": prev_section_url, }, ) result = render_to_response("courseware/courseware.html", context) except Exception as e: if isinstance(e, Http404): # let it propagate raise # In production, don't want to let a 500 out for any reason if settings.DEBUG: raise else: log.exception( "Error in index view: user={user}, course={course}," " chapter={chapter} section={section}" "position={position}".format( user=user, course=course, chapter=chapter, section=section, position=position ) ) try: result = render_to_response( "courseware/courseware-error.html", {"staff_access": staff_access, "course": course} ) except: # Let the exception propagate, relying on global config to at # at least return a nice error message log.exception("Error while rendering courseware-error page") raise return result
def fullstat(request = None): request = DummyRequest() header = [u'ФИО', u'ФИО (измененное)', u'логин школы', u'email', u'email (измененное)', u'курс', u'зарег. в пакет рег.', u"дата рег. на курс", u'2/3', u'100%', u'Задачи/Задания(Модули)'] assignments = [] datatablefull = {'header': header, 'assignments': assignments, 'students': []} datafull = [] for course in modulestore().get_courses(): datarow = [u'-', u'-', u'-', u'-', u'-', course.id, u'-', u'-', u'-'] assignments = [] enrolled_students = User.objects.filter( courseenrollment__course_id=course.id, ).prefetch_related("groups").order_by('username') enrolled_students = [st for st in enrolled_students if not _has_staff_access_to_course_id(st, course.id)] if len(enrolled_students) <= 0: continue gradeset = student_grades(enrolled_students[0], request, course, keep_raw_scores=True, use_offline=False) courseware_summary = grades.progress_summary(enrolled_students[0], request, course); if courseware_summary is None: continue assignments += [score.section for score in gradeset['raw_scores']] for chapter in courseware_summary: for section in chapter['sections']: if not section['graded'] or len(section['format']) < 1: continue assignments += [section['format']] assignments += [chapter['display_name']] datarow += assignments datafull.append(datarow) edxdata = gendata(request) print("Dumping fullstat") f = open("/opt/data.csv") if f is None: return False; ff = UnicodeDictReader(f, delimiter=';', quoting=csv.QUOTE_NONE) usermap = {} idx = 0 for row in ff: idx += 1 usermap.setdefault(row['email'],[]).append(row) for course in modulestore().get_courses(): enrolled_students = User.objects.filter( courseenrollment__course_id=course.id, courseenrollment__is_active=1, ).prefetch_related("groups").order_by('username') enrolled_students = [st for st in enrolled_students if not _has_staff_access_to_course_id(st, course.id)] idx = 0 for user in enrolled_students: try: idx += 1 datarow = [] found = False rows = [] try: for elem in user.profile.get_meta().get('old_emails',[])[::-1]: if usermap[elem[0]]: found = True rows = usermap[elem[0]] break if not found and usermap[user.email]: found = True rows = usermap[user.email] except: pass off_reg = False try: for row in rows: found = False for course_id, course_name in coursemap.iteritems(): if course_name in row['subject']: found = True off_reg = True break if found: break except: pass #User name = '' try: name = rows[0]['second-name'] + ' ' + rows[0]['first-name'] + ' ' + rows[0]['patronymic'] except: pass datarow += [name] if user.profile.name != name: datarow += [user.profile.name] else: datarow += [u''] try: datarow += [rows[0]['login']] except: datarow += [''] email = '' try: datarow += [rows[0]['email']] email = rows[0]['email'] except: datarow += [''] if user.email != email: datarow += [user.email] else: datarow += [u''] #Course datarow += [course.display_name] if off_reg: datarow += [u'Да'] else: datarow += [u'Нет'] try: courseenrollment = user.courseenrollment_set.filter(course_id = course.id)[0] datarow += [courseenrollment.created.strftime('%d/%m/%Y')] except: continue #Raw statistic by problems statprob = edxdata[course.id][user.email]["prob_info"] #By subsection statsec = edxdata[course.id][user.email]["sec_info"] if edxdata[course.id][user.email]["0.7"]: datarow += [u"Да"] else: datarow += [u"Нет"] if edxdata[course.id][user.email]["1.0"]: datarow += [u"Да"] else: datarow += [u"Нет"] if len(statsec) > 0 and len(statprob) > 0: datarow += statprob datarow += statsec datafull.append(datarow) except: logging.exception("Something awful happened in fullstat!") pass datatablefull['data'] = datafull return_csv('full_stat.csv',datatablefull, open("/var/www/edx/fullstat.csv", "wb")) for course in modulestore().get_courses(): print("Dumping course {courseid}".format(courseid = course.id)) assignments = [] enrolled_students = User.objects.filter( courseenrollment__course_id=course.id, ).prefetch_related("groups").order_by('username') enrolled_students = [st for st in enrolled_students if not _has_staff_access_to_course_id(st, course.id)] if len(enrolled_students) <= 0: continue gradeset = student_grades(enrolled_students[0], request, course, keep_raw_scores=True, use_offline=False) courseware_summary = grades.progress_summary(enrolled_students[0], request, course); if courseware_summary is None: print "No courseware_summary" continue assignments += [score.section for score in gradeset['raw_scores']] for chapter in courseware_summary: for section in chapter['sections']: if not section['graded'] or len(section['format']) < 1: continue assignments += [section['format']] assignments += [chapter['display_name']] header = [u'ФИО', u'логин школы', u'email', u"дата регистрации на курс", u'2/3', u'100%'] header += assignments datatable = {'header': header, 'assignments': assignments, 'students': []} data = [] for user in enrolled_students: try: datarow = [] #User name = user.profile.name datarow += [name] datarow += [user.profile.work_login] datarow += [user.email] courseenrollment = user.courseenrollment_set.filter(course_id = course.id)[0] datarow += [courseenrollment.created.strftime('%d/%m/%Y')] #Raw statistic by problems statprob = edxdata[course.id][user.email]["prob_info"] #By subsection statsec = edxdata[course.id][user.email]["sec_info"] if edxdata[course.id][user.email]["0.7"]: datarow += [u"Да"] else: datarow += [u"Нет"] if edxdata[course.id][user.email]["1.0"]: datarow += [u"Да"] else: datarow += [u"Нет"] if len(statsec) > 0 and len(statprob) > 0: datarow += statprob datarow += statsec else: datarow += [0] * len(assignments) data.append(datarow) except: logging.exception("Something awful happened in {course_id}!".format(course_id = course.id)) pass datatable['data'] = data return_csv(course.id,datatable, open("/var/www/edx/" + course.id.replace('/','_') + ".xls", "wb"), encoding="cp1251", dialect="excel-tab") return_csv(course.id,datatable, open("/var/www/edx/" + course.id.replace('/','_') + ".csv", "wb")) return True
def handle(self, *args, **options): help = "Command to create or update gradebook entries" option_list = BaseCommand.option_list + ( make_option( "-c", "--course_ids", dest="course_ids", help="List of courses for which to generate grades", metavar="first/course/id,second/course/id" ), make_option( "-u", "--user_ids", dest="user_ids", help="List of users for which to generate grades", metavar="1234,2468,3579" ), ) course_ids = options.get('course_ids') user_ids = options.get('user_ids') # Get the list of courses from the system courses = modulestore().get_courses() # If one or more courses were specified by the caller, just use those ones... if course_ids is not None: filtered_courses = [] for course in courses: if unicode(course.id) in course_ids.split(','): filtered_courses.append(course) courses = filtered_courses for course in courses: users = CourseEnrollment.objects.users_enrolled_in(course.id) # If one or more users were specified by the caller, just use those ones... if user_ids is not None: filtered_users = [] for user in users: if str(user.id) in user_ids.split(','): filtered_users.append(user) users = filtered_users # For each user... for user in users: request = RequestMockWithoutMiddleware().get('/') request.user = user grade_data = grades.grade(user, request, course) grade = grade_data['percent'] grading_policy = course.grading_policy proforma_grade = grades.calculate_proforma_grade(grade_data, grading_policy) progress_summary = grades.progress_summary(user, request, course) try: gradebook_entry = StudentGradebook.objects.get(user=user, course_id=course.id) if (gradebook_entry.grade != grade or gradebook_entry.proforma_grade != proforma_grade or gradebook_entry.progress_summary != progress_summary or gradebook_entry.grade_summary != grade_data or gradebook_entry.grading_policy != grading_policy): gradebook_entry.grade = grade gradebook_entry.proforma_grade = proforma_grade gradebook_entry.progress_summary = json.dumps(progress_summary, cls=EdxJSONEncoder) gradebook_entry.grade_summary = json.dumps(grade_data, cls=EdxJSONEncoder) gradebook_entry.grading_policy = json.dumps(grading_policy, cls=EdxJSONEncoder) gradebook_entry.save() except StudentGradebook.DoesNotExist: StudentGradebook.objects.create( user=user, course_id=course.id, grade=grade, proforma_grade=proforma_grade, progress_summary=json.dumps(progress_summary, cls=EdxJSONEncoder), grade_summary=json.dumps(grade_data, cls=EdxJSONEncoder), grading_policy=json.dumps(grading_policy, cls=EdxJSONEncoder) ) log_msg = 'Gradebook entry created -- Course: {}, User: {} (grade: {}, proforma_grade: {})'.format(course.id, user.id, grade, proforma_grade) print log_msg log.info(log_msg)
def gendata(request): data = {} for course in modulestore().get_courses(): data[course.id] = {} print("Loading info for course {courseid}".format(courseid = course.id)) enrolled_students = User.objects.filter( courseenrollment__course_id=course.id, ).prefetch_related("groups").order_by('username') enrolled_students = [st for st in enrolled_students if not _has_staff_access_to_course_id(st, course.id)] if len(enrolled_students) <= 0: continue #Category weights gradeset = student_grades(enrolled_students[0], request, course, keep_raw_scores=False, use_offline=False) category_weights = {} for section in gradeset['grade_breakdown']: category_weights[section['category']] = section['weight'] for user in enrolled_students: data[course.id][user.email] = {} #User data[course.id][user.email]["user"] = user #Raw statistic by problems gradeset = student_grades(user, request, course, keep_raw_scores=True, use_offline=False) statprob = [(getattr(score, 'earned', '') or score[0]) for score in gradeset['raw_scores']] #By subsection statsec = [] complition = 0 complition_cnt = 0 try: courseware_summary = grades.progress_summary(user, request, course); for chapter in courseware_summary: total = 0 flag = False for section in chapter['sections']: if not section['graded'] or len(section['format']) < 1: continue flag = True statsec += [((section['section_total'].earned / section['section_total'].possible) if section['section_total'].possible else 0)] total += ((section['section_total'].earned / section['section_total'].possible) if section['section_total'].possible else 0) * category_weights.get(section['format'], 0.0) statsec += [total] if flag: complition += total complition_cnt += 1 except: pass if complition_cnt == 0: complition = 0 else: complition = complition / complition_cnt if complition > 0.7: data[course.id][user.email]["0.7"] = True else: data[course.id][user.email]["0.7"] = False if complition > 0.99: data[course.id][user.email]["1.0"] = True else: data[course.id][user.email]["1.0"] = False data[course.id][user.email]["prob_info"] = statprob data[course.id][user.email]["sec_info"] = statsec print("Loading info for course {courseid} - COMPLETE - total {users}".format(courseid = course.id, users = len (data[course.id]) )) return data
def index(request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, redirects to user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: - request : HTTP request - course_id : course id (str: ORG/course/URL_NAME) - chapter : chapter url_name (str) - section : section url_name (str) - position : position in module, eg of <sequential> module (str) Returns: - HTTPresponse """ user = User.objects.prefetch_related("groups").get(id=request.user.id) request.user = user # keep just one instance of User # Если пользователь не активен - отправляем на главную страницу if not user.is_active and not user.profile.is_demo: return redirect('/') try: course = get_course_with_access(user, course_id, 'load', depth=2) except: return redirect('/') # Если курс помечен, как непубликуемый в LMS - отправляем на главную страницу if not course.show_in_lms: return redirect('/') staff_access = has_access(user, course, 'staff') registered = registered_for_course(course, user) if not registered: # TODO (vshnayder): do course instructors need to be registered to see course? log.debug('User %s tried to view course %s but is not enrolled' % (user, course.location.url())) return redirect(reverse('about_course', args=[course.id])) masq = setup_masquerade(request, staff_access) try: field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, user, course, depth=2) course_module = get_module_for_descriptor(user, request, course, field_data_cache, course.id) if course_module is None: log.warning('If you see this, something went wrong: if we got this' ' far, should have gotten a course module for this user') return redirect(reverse('about_course', args=[course.id])) if chapter is None: return redirect_to_course_position(course_module) context = { 'csrf': csrf(request)['csrf_token'], 'accordion': render_accordion(request, course, chapter, section, field_data_cache), 'COURSE_TITLE': course.display_name_with_default, 'course': course, 'init': '', 'fragment': Fragment(), 'staff_access': staff_access, 'masquerade': masq, 'xqa_server': settings.FEATURES.get('USE_XQA_SERVER', 'http://*****:*****@content-qa.mitx.mit.edu/xqa') } # Only show the chat if it's enabled by the course and in the # settings. show_chat = course.show_chat and settings.FEATURES['ENABLE_CHAT'] if show_chat: context['chat'] = chat_settings(course, user) # If we couldn't load the chat settings, then don't show # the widget in the courseware. if context['chat'] is None: show_chat = False context['show_chat'] = show_chat chapter_descriptor = course.get_child_by(lambda m: m.url_name == chapter) if chapter_descriptor is not None: save_child_position(course_module, chapter) else: raise Http404('No chapter descriptor found with name {}'.format(chapter)) chapter_module = course_module.get_child_by(lambda m: m.url_name == chapter) if chapter_module is None: # User may be trying to access a chapter that isn't live yet if masq=='student': # if staff is masquerading as student be kinder, don't 404 log.debug('staff masq as student: no chapter %s' % chapter) return redirect(reverse('courseware', args=[course.id])) raise Http404 if section is not None: section_descriptor = chapter_descriptor.get_child_by(lambda m: m.url_name == section) if section_descriptor is None: # Specifically asked-for section doesn't exist if masq=='student': # if staff is masquerading as student be kinder, don't 404 log.debug('staff masq as student: no section %s' % section) return redirect(reverse('courseware', args=[course.id])) raise Http404 # cdodge: this looks silly, but let's refetch the section_descriptor with depth=None # which will prefetch the children more efficiently than doing a recursive load section_descriptor = modulestore().get_instance(course.id, section_descriptor.location, depth=None) # Load all descendants of the section, because we're going to display its # html, which in general will need all of its children section_field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, user, section_descriptor, depth=None) section_module = get_module_for_descriptor(request.user, request, section_descriptor, section_field_data_cache, course_id, position ) if section_module is None: # User may be trying to be clever and access something # they don't have access to. raise Http404 # model_data_cache_for_check = ModelDataCache.cache_for_descriptor_descendents(course_id, user, course, depth=None) courseware_summary = grades.progress_summary(user, request, course) is_section_unlocked = grades.return_section_by_id(section_module.url_name, courseware_summary)['unlocked'] #Контент раздела закрыт для демопользователя is_demo = UserProfile.objects.get(user=request.user).is_demo if is_demo and not section_module.available_for_demo: is_section_unlocked = False # Save where we are in the chapter save_child_position(chapter_module, section) context['fragment'] = section_module.render('student_view', context) else: # section is none, so display a message prev_section = get_current_child(chapter_module) if prev_section is None: # Something went wrong -- perhaps this chapter has no sections visible to the user raise Http404 prev_section_url = reverse('courseware_section', kwargs={'course_id': course_id, 'chapter': chapter_descriptor.url_name, 'section': prev_section.url_name}) context['fragment'] = Fragment(content=render_to_string( 'courseware/welcome-back.html', { 'course': course, 'chapter_module': chapter_module, 'prev_section': prev_section, 'prev_section_url': prev_section_url } )) result = render_to_response('courseware/courseware.html', context) except Exception as e: if isinstance(e, Http404): # let it propagate raise # In production, don't want to let a 500 out for any reason if settings.DEBUG: raise else: log.exception("Error in index view: user={user}, course={course}," " chapter={chapter} section={section}" "position={position}".format( user=user, course=course, chapter=chapter, section=section, position=position )) try: result = render_to_response('courseware/courseware-error.html', {'staff_access': staff_access, 'course': course}) except: # Let the exception propagate, relying on global config to at # at least return a nice error message log.exception("Error while rendering courseware-error page") raise return result
def course_data(request, course_id): """ Get course's data(title, short description), Total Points/Earned Points or 404 if there is no such course. Assumes the course_id is in a valid format. """ course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) with modulestore().bulk_operations(course_key): course = get_course_with_access(request.user, 'load', course_key, depth=None, check_if_enrolled=True) access_response = has_access(request.user, 'load', course, course_key) context={} if course.has_started(): staff_access = bool(has_access(request.user, 'staff', course)) student = request.user # NOTE: To make sure impersonation by instructor works, use # student instead of request.user in the rest of the function. # The pre-fetching of groups is done to make auth checks not require an # additional DB lookup (this kills the Progress page in particular). student = User.objects.prefetch_related("groups").get(id=student.id) with outer_atomic(): field_data_cache = grades.field_data_cache_for_grading(course, student) scores_client = ScoresClient.from_field_data_cache(field_data_cache) title = course.display_name_with_default loc = course.location.replace(category='about', name='short_description') about_module = get_module( request.user, request, loc, field_data_cache, log_if_not_found=False, wrap_xmodule_display=False, static_asset_path=course.static_asset_path, course=course ) short_description = about_module.render(STUDENT_VIEW).content courseware_summary = grades.progress_summary( student, request, course, field_data_cache=field_data_cache, scores_client=scores_client ) grade_summary = grades.grade( student, request, course, field_data_cache=field_data_cache, scores_client=scores_client ) total_points = 0 earned_points = 0 for chapter in courseware_summary: for section in chapter['sections']: total_points += section['section_total'].possible earned_points += section['section_total'].earned percentage_points = float(earned_points)*(100.0/float(total_points)) context = { "started": course.has_started(), "course_image": course_image_url(course), "total": total_points, "earned": earned_points, "percentage": percentage_points, 'title': title, 'short_description' : short_description, 'staff_access': staff_access, 'student': student.id, 'passed': is_course_passed(course, grade_summary), } else: context={ "started": course.has_started(), } return JsonResponse(context)