def _lookup_team_membership_data(course): """ Returns a list of dicts, in the following form: [ { 'user': <username>, 'mode': <student enrollment mode for the given course>, <teamset id>: <team name> for each teamset in which the given user is on a team } for student in course ] """ course_students = CourseEnrollment.objects.users_enrolled_in( course.id).order_by('username') CourseEnrollment.bulk_fetch_enrollment_states(course_students, course.id) course_team_memberships = CourseTeamMembership.objects.filter( team__course_id=course.id).select_related('team', 'user').all() teamset_memberships_by_user = _group_teamset_memberships_by_user( course_team_memberships) team_membership_data = [] for user in course_students: student_row = teamset_memberships_by_user.get(user, dict()) student_row['user'] = user.username student_row['mode'], _ = CourseEnrollment.enrollment_mode_for_user( user, course.id) team_membership_data.append(student_row) return team_membership_data
def bulk_gradebook_view_context(course_key, users): """ Prefetches all course and subsection grades in the given course for the given list of users, also, fetch all the score relavant data, storing the result in a RequestCache and deleting grades on context exit. """ prefetch_course_and_subsection_grades(course_key, users) CourseEnrollment.bulk_fetch_enrollment_states(users, course_key) cohorts.bulk_cache_cohorts(course_key, users) BulkRoleCache.prefetch(users) try: yield finally: clear_prefetched_course_and_subsection_grades(course_key)
def bulk_gradebook_view_context(course_key, users): """ Prefetches all course and subsection grades in the given course for the given list of users, also, fetch all the score relavant data, storing the result in a RequestCache and deleting grades on context exit. """ PersistentSubsectionGrade.prefetch(course_key, users) PersistentCourseGrade.prefetch(course_key, users) CourseEnrollment.bulk_fetch_enrollment_states(users, course_key) cohorts.bulk_cache_cohorts(course_key, users) BulkRoleCache.prefetch(users) yield PersistentSubsectionGrade.clear_prefetched_data(course_key) PersistentCourseGrade.clear_prefetched_data(course_key)
def generate(cls, _xmodule_instance_args, _entry_id, course_id, _task_input, action_name): """ Generate a CSV containing all students' problem grades within a given `course_id`. """ start_time = time() start_date = datetime.now(UTC) status_interval = 100 enrolled_students = CourseEnrollment.objects.users_enrolled_in(course_id, include_inactive=True) task_progress = TaskProgress(action_name, enrolled_students.count(), start_time) # This struct encapsulates both the display names of each static item in the # header row as values as well as the django User field names of those items # as the keys. It is structured in this way to keep the values related. header_row = OrderedDict([('id', 'Student ID'), ('email', 'Email'), ('username', 'Username')]) course = get_course_by_id(course_id) graded_scorable_blocks = cls._graded_scorable_blocks_to_header(course) # Just generate the static fields for now. rows = [list(header_row.values()) + ['Enrollment Status', 'Grade'] + _flatten(graded_scorable_blocks.values())] error_rows = [list(header_row.values()) + ['error_msg']] current_step = {'step': 'Calculating Grades'} # Bulk fetch and cache enrollment states so we can efficiently determine # whether each user is currently enrolled in the course. CourseEnrollment.bulk_fetch_enrollment_states(enrolled_students, course_id) for student, course_grade, error in CourseGradeFactory().iter(enrolled_students, course): student_fields = [getattr(student, field_name) for field_name in header_row] task_progress.attempted += 1 if not course_grade: err_msg = text_type(error) # There was an error grading this student. if not err_msg: err_msg = u'Unknown error' error_rows.append(student_fields + [err_msg]) task_progress.failed += 1 continue enrollment_status = _user_enrollment_status(student, course_id) earned_possible_values = [] for block_location in graded_scorable_blocks: try: problem_score = course_grade.problem_scores[block_location] except KeyError: earned_possible_values.append([u'Not Available', u'Not Available']) else: if problem_score.first_attempted: earned_possible_values.append([problem_score.earned, problem_score.possible]) else: earned_possible_values.append([u'Not Attempted', problem_score.possible]) rows.append(student_fields + [enrollment_status, course_grade.percent] + _flatten(earned_possible_values)) task_progress.succeeded += 1 if task_progress.attempted % status_interval == 0: task_progress.update_task_state(extra_meta=current_step) # Perform the upload if any students have been successfully graded if len(rows) > 1: upload_csv_to_report_store(rows, 'problem_grade_report', course_id, start_date) # If there are any error rows, write them out as well if len(error_rows) > 1: upload_csv_to_report_store(error_rows, 'problem_grade_report_err', course_id, start_date) return task_progress.update_task_state(extra_meta={'step': 'Uploading CSV'})
def __init__(self, context, users): CourseEnrollment.bulk_fetch_enrollment_states(users, context.course_id) self.verified_users = [ verified.user.id for verified in IDVerificationService.get_verified_users(users) ]
def __init__(self, context, users): CourseEnrollment.bulk_fetch_enrollment_states(users, context.course_id) self.verified_users = set(IDVerificationService.get_verified_user_ids(users))
def __init__(self, context, users): CourseEnrollment.bulk_fetch_enrollment_states(users, context.course_id) self.verified_users = [ verified.user.id for verified in SoftwareSecurePhotoVerification.verified_query().filter(user__in=users).select_related('user__id') ]
def generate(cls, _xmodule_instance_args, _entry_id, course_id, _task_input, action_name): """ Generate a CSV containing all students' problem grades within a given `course_id`. """ def log_task_info(message): """ Updates the status on the celery task to the given message. Also logs the update. """ fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}' task_info_string = fmt.format(task_id=task_id, entry_id=_entry_id, course_id=course_id, task_input=_task_input) TASK_LOG.info(u'%s, Task type: %s, %s, %s', task_info_string, action_name, message, task_progress.state) start_time = time() start_date = datetime.now(UTC) status_interval = 100 task_id = _xmodule_instance_args.get( 'task_id') if _xmodule_instance_args is not None else None enrolled_students = CourseEnrollment.objects.users_enrolled_in( course_id, include_inactive=True, verified_only=problem_grade_report_verified_only(course_id), ) task_progress = TaskProgress(action_name, enrolled_students.count(), start_time) # This struct encapsulates both the display names of each static item in the # header row as values as well as the django User field names of those items # as the keys. It is structured in this way to keep the values related. header_row = OrderedDict([('id', 'Student ID'), ('email', 'Email'), ('username', 'Username')]) course = get_course_by_id(course_id) log_task_info(u'Retrieving graded scorable blocks') graded_scorable_blocks = cls._graded_scorable_blocks_to_header(course) # Just generate the static fields for now. rows = [ list(header_row.values()) + ['Enrollment Status', 'Grade'] + _flatten(list(graded_scorable_blocks.values())) ] error_rows = [list(header_row.values()) + ['error_msg']] # Bulk fetch and cache enrollment states so we can efficiently determine # whether each user is currently enrolled in the course. log_task_info(u'Fetching enrollment status') CourseEnrollment.bulk_fetch_enrollment_states(enrolled_students, course_id) for student, course_grade, error in CourseGradeFactory().iter( enrolled_students, course): student_fields = [ getattr(student, field_name) for field_name in header_row ] task_progress.attempted += 1 if not course_grade: err_msg = text_type(error) # There was an error grading this student. if not err_msg: err_msg = u'Unknown error' error_rows.append(student_fields + [err_msg]) task_progress.failed += 1 continue enrollment_status = _user_enrollment_status(student, course_id) earned_possible_values = [] for block_location in graded_scorable_blocks: try: problem_score = course_grade.problem_scores[block_location] except KeyError: earned_possible_values.append( [u'Not Available', u'Not Available']) else: if problem_score.first_attempted: earned_possible_values.append( [problem_score.earned, problem_score.possible]) else: earned_possible_values.append( [u'Not Attempted', problem_score.possible]) rows.append(student_fields + [enrollment_status, course_grade.percent] + _flatten(earned_possible_values)) task_progress.succeeded += 1 if task_progress.attempted % status_interval == 0: step = u'Calculating Grades' task_progress.update_task_state(extra_meta={'step': step}) log_message = u'{0} {1}/{2}'.format(step, task_progress.attempted, task_progress.total) log_task_info(log_message) log_task_info('Uploading CSV to store') # Perform the upload if any students have been successfully graded if len(rows) > 1: upload_csv_to_report_store(rows, 'problem_grade_report', course_id, start_date) # If there are any error rows, write them out as well if len(error_rows) > 1: upload_csv_to_report_store(error_rows, 'problem_grade_report_err', course_id, start_date) return task_progress.update_task_state( extra_meta={'step': 'Uploading CSV'})
def __init__(self, context, users): CourseEnrollment.bulk_fetch_enrollment_states(users, context.course_id) self.verified_users = [ verified.user.id for verified in SoftwareSecurePhotoVerification. verified_query().filter(user__in=users).select_related('user__id') ]