Enable use of student usernames on student admin page
This is in addition to email addresses, which also work.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user