From 07e76b3b2f92d7f97e2ad1f3a3f094885426b55e Mon Sep 17 00:00:00 2001 From: Sarina Canelake Date: Thu, 26 Sep 2013 08:09:09 -0400 Subject: [PATCH] Enable use of student usernames on student admin page This is in addition to email addresses, which also work. --- lms/djangoapps/instructor/views/api.py | 53 ++++++++++--------- lms/djangoapps/instructor/views/tools.py | 17 ++++++ .../instructor_dashboard/student_admin.coffee | 22 ++++---- 3 files changed, 55 insertions(+), 37 deletions(-) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 8a552feb66..9e58ecea5f 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -33,7 +33,7 @@ import instructor_task.api from instructor_task.api_helper import AlreadyRunningError import instructor.enrollment as enrollment from instructor.enrollment import enroll_email, unenroll_email -from instructor.views.tools import strip_if_string +from instructor.views.tools import strip_if_string, get_student_from_identifier import instructor.access as access import analytics.basic import analytics.distributions @@ -456,20 +456,19 @@ def get_distribution(request, course_id): @common_exceptions_400 @require_level('staff') @require_query_params( - student_email="email of student for whom to get progress url" + unique_student_identifier="email or username of student for whom to get progress url" ) def get_student_progress_url(request, course_id): """ Get the progress url of a student. Limited to staff access. - Takes query paremeter student_email and if the student exists + Takes query paremeter unique_student_identifier and if the student exists returns e.g. { 'progress_url': '/../...' } """ - student_email = strip_if_string(request.GET.get('student_email')) - user = User.objects.get(email=student_email) + user = get_student_from_identifier(request.GET.get('unique_student_identifier')) progress_url = reverse('student_progress', kwargs={'course_id': course_id, 'student_id': user.id}) @@ -496,7 +495,7 @@ def reset_student_attempts(request, course_id): Takes some of the following query paremeters - problem_to_reset is a urlname of a problem - - student_email is an email + - unique_student_identifier is an email or username - all_students is a boolean requires instructor access mutually exclusive with delete_module @@ -510,14 +509,14 @@ def reset_student_attempts(request, course_id): ) problem_to_reset = strip_if_string(request.GET.get('problem_to_reset')) - student_email = strip_if_string(request.GET.get('student_email')) + student = get_student_from_identifier(request.GET.get('unique_student_identifier')) all_students = request.GET.get('all_students', False) in ['true', 'True', True] delete_module = request.GET.get('delete_module', False) in ['true', 'True', True] # parameter combinations - if all_students and student_email: + if all_students and student: return HttpResponseBadRequest( - "all_students and student_email are mutually exclusive." + "all_students and unique_student_identifier are mutually exclusive." ) if all_students and delete_module: return HttpResponseBadRequest( @@ -534,9 +533,8 @@ def reset_student_attempts(request, course_id): response_payload = {} response_payload['problem_to_reset'] = problem_to_reset - if student_email: + if student: try: - student = User.objects.get(email=student_email) enrollment.reset_student_attempts(course_id, student, module_state_key, delete_module=delete_module) except StudentModule.DoesNotExist: return HttpResponseBadRequest("Module does not exist.") @@ -561,21 +559,24 @@ def rescore_problem(request, course_id): Takes either of the following query paremeters - problem_to_reset is a urlname of a problem - - student_email is an email + - unique_student_identifier is an email or username - all_students is a boolean - all_students and student_email cannot both be present. + all_students and unique_student_identifier cannot both be present. """ problem_to_reset = strip_if_string(request.GET.get('problem_to_reset')) - student_email = strip_if_string(request.GET.get('student_email', False)) + student = request.GET.get('unique_student_identifier', None) + if student is not None: + student = get_student_from_identifier(student) + all_students = request.GET.get('all_students') in ['true', 'True', True] - if not (problem_to_reset and (all_students or student_email)): + if not (problem_to_reset and (all_students or student)): return HttpResponseBadRequest("Missing query parameters.") - if all_students and student_email: + if all_students and student: return HttpResponseBadRequest( - "Cannot rescore with all_students and student_email." + "Cannot rescore with all_students and unique_student_identifier." ) module_state_key = _msk_from_problem_urlname(course_id, problem_to_reset) @@ -583,9 +584,8 @@ def rescore_problem(request, course_id): response_payload = {} response_payload['problem_to_reset'] = problem_to_reset - if student_email: - response_payload['student_email'] = student_email - student = User.objects.get(email=student_email) + if student: + response_payload['student'] = student instructor_task.api.submit_rescore_problem_for_student(request, course_id, module_state_key, student) response_payload['task'] = 'created' elif all_students: @@ -608,21 +608,22 @@ def list_instructor_tasks(request, course_id): Takes optional query paremeters. - With no arguments, lists running tasks. - `problem_urlname` lists task history for problem - - `problem_urlname` and `student_email` lists task + - `problem_urlname` and `unique_student_identifier` lists task history for problem AND student (intersection) """ problem_urlname = strip_if_string(request.GET.get('problem_urlname', False)) - student_email = strip_if_string(request.GET.get('student_email', False)) + student = request.GET.get('unique_student_identifier', None) + if student is not None: + student = get_student_from_identifier(student) - if student_email and not problem_urlname: + if student and not problem_urlname: return HttpResponseBadRequest( - "student_email must accompany problem_urlname" + "unique_student_identifier must accompany problem_urlname" ) if problem_urlname: module_state_key = _msk_from_problem_urlname(course_id, problem_urlname) - if student_email: - student = User.objects.get(email=student_email) + if student: tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key, student) else: tasks = instructor_task.api.get_instructor_task_history(course_id, module_state_key) diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index 11fc135976..eab0e66196 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -1,7 +1,24 @@ """ Tools for the instructor dashboard """ +from django.contrib.auth.models import User + def strip_if_string(value): if isinstance(value, basestring): return value.strip() return value + +def get_student_from_identifier(unique_student_identifier): + """ + Gets a student object using either an email address or username. + + Returns the student object associated with `unique_student_identifier` + + Raises User.DoesNotExist if no user object can be found. + """ + unique_student_identifier = strip_if_string(unique_student_identifier) + if "@" in unique_student_identifier: + student = User.objects.get(email=unique_student_identifier) + else: + student = User.objects.get(username=unique_student_identifier) + return student diff --git a/lms/static/coffee/src/instructor_dashboard/student_admin.coffee b/lms/static/coffee/src/instructor_dashboard/student_admin.coffee index e607a463fc..10d83c4a00 100644 --- a/lms/static/coffee/src/instructor_dashboard/student_admin.coffee +++ b/lms/static/coffee/src/instructor_dashboard/student_admin.coffee @@ -118,15 +118,15 @@ class StudentAdmin # go to student progress page @$progress_link.click (e) => e.preventDefault() - email = @$field_student_select_progress.val() + unique_student_identifier = @$field_student_select_progress.val() $.ajax dataType: 'json' url: @$progress_link.data 'endpoint' - data: student_email: email + data: unique_student_identifier: unique_student_identifier success: @clear_errors_then (data) -> window.location = data.progress_url - error: std_ajax_err => @$request_response_error_single.text "Error getting student progress url for '#{email}'." + error: std_ajax_err => @$request_response_error_single.text "Error getting student progress url for '#{unique_student_identifier}'." # enroll student @$btn_enroll.click => @@ -158,7 +158,7 @@ class StudentAdmin # reset attempts for student on problem @$btn_reset_attempts_single.click => send_data = - student_email: @$field_student_select_grade.val() + unique_student_identifier: @$field_student_select_grade.val() problem_to_reset: @$field_problem_select_single.val() delete_module: false @@ -167,14 +167,14 @@ class StudentAdmin url: @$btn_reset_attempts_single.data 'endpoint' data: send_data success: @clear_errors_then -> console.log 'problem attempts reset' - error: std_ajax_err => @$request_response_error_single.text "Error resetting problem attempts." + error: std_ajax_err => @$request_response_error_single.text "Error resetting problem attempts for problem '#{problem_to_reset}' and student '#{unique_student_identifier}'." # delete state for student on problem @$btn_delete_state_single.click => confirm_then msg: "Delete student '#{@$field_student_select_grade.val()}'s state on problem '#{@$field_problem_select_single.val()}'?" ok: => send_data = - student_email: @$field_student_select_grade.val() + unique_student_identifier: @$field_student_select_grade.val() problem_to_reset: @$field_problem_select_single.val() delete_module: true @@ -188,7 +188,7 @@ class StudentAdmin # start task to rescore problem for student @$btn_rescore_problem_single.click => send_data = - student_email: @$field_student_select_grade.val() + unique_student_identifier: @$field_student_select_grade.val() problem_to_reset: @$field_problem_select_single.val() $.ajax @@ -201,13 +201,13 @@ class StudentAdmin # list task history for student+problem @$btn_task_history_single.click => send_data = - student_email: @$field_student_select_grade.val() + unique_student_identifier: @$field_student_select_grade.val() problem_urlname: @$field_problem_select_single.val() - if not send_data.student_email - return @$request_response_error_single.text "Enter a student email." + if not send_data.unique_student_identifier + return @$request_response_error_single.text "Please enter a student email address or username." if not send_data.problem_urlname - return @$request_response_error_single.text "Enter a problem urlname." + return @$request_response_error_single.text "Please enter a problem urlname." $.ajax dataType: 'json'