Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
9dc48c00
Commit
9dc48c00
authored
May 20, 2014
by
Sarina Canelake
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3779 from edx/sarina/fix-grades-management-commands
Sarina/fix grades management commands
parents
80552674
189f53bc
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
88 additions
and
52 deletions
+88
-52
common/djangoapps/student/management/commands/get_grades.py
+23
-7
lms/djangoapps/instructor/management/commands/compute_grades.py
+19
-11
lms/djangoapps/instructor/management/commands/dump_grades.py
+21
-12
lms/djangoapps/instructor/offline_gradecalc.py
+13
-10
lms/djangoapps/instructor/views/legacy.py
+12
-12
No files found.
common/djangoapps/student/management/commands/get_grades.py
View file @
9dc48c00
...
...
@@ -3,6 +3,9 @@ from certificates.models import GeneratedCertificate
from
django.test.client
import
RequestFactory
from
django.core.management.base
import
BaseCommand
,
CommandError
import
os
from
opaque_keys
import
InvalidKeyError
from
xmodule.modulestore.keys
import
CourseKey
from
xmodule.modulestore.locations
import
SlashSeparatedCourseKey
from
django.contrib.auth.models
import
User
from
optparse
import
make_option
import
datetime
...
...
@@ -62,24 +65,37 @@ class Command(BaseCommand):
options
[
'output'
]))
STATUS_INTERVAL
=
100
course_id
=
options
[
'course'
]
print
"Fetching enrolled students for {0}"
.
format
(
course_id
)
# parse out the course into a coursekey
if
options
[
'course'
]:
try
:
course_key
=
CourseKey
.
from_string
(
options
[
'course'
])
# if it's not a new-style course key, parse it from an old-style
# course key
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
options
[
'course'
])
print
"Fetching enrolled students for {0}"
.
format
(
course_key
)
enrolled_students
=
User
.
objects
.
filter
(
courseenrollment__course_id
=
course_id
)
courseenrollment__course_id
=
course_key
)
factory
=
RequestMock
()
request
=
factory
.
get
(
'/'
)
total
=
enrolled_students
.
count
()
print
"Total enrolled: {0}"
.
format
(
total
)
course
=
courses
.
get_course_by_id
(
course_
id
)
course
=
courses
.
get_course_by_id
(
course_
key
)
total
=
enrolled_students
.
count
()
start
=
datetime
.
datetime
.
now
()
rows
=
[]
header
=
None
print
"Fetching certificate data"
cert_grades
=
{
cert
.
user
.
username
:
cert
.
grade
for
cert
in
list
(
GeneratedCertificate
.
objects
.
filter
(
course_id
=
course_id
)
.
prefetch_related
(
'user'
))}
cert_grades
=
{
cert
.
user
.
username
:
cert
.
grade
for
cert
in
list
(
GeneratedCertificate
.
objects
.
filter
(
course_id
=
course_key
)
.
prefetch_related
(
'user'
)
)
}
print
"Grading students"
for
count
,
student
in
enumerate
(
enrolled_students
):
count
+=
1
...
...
lms/djangoapps/instructor/management/commands/compute_grades.py
View file @
9dc48c00
...
...
@@ -6,6 +6,9 @@
from
instructor.offline_gradecalc
import
offline_grade_calculation
from
courseware.courses
import
get_course_by_id
from
xmodule.modulestore.django
import
modulestore
from
opaque_keys
import
InvalidKeyError
from
xmodule.modulestore.keys
import
CourseKey
from
xmodule.modulestore.locations
import
SlashSeparatedCourseKey
from
django.core.management.base
import
BaseCommand
...
...
@@ -25,19 +28,24 @@ class Command(BaseCommand):
else
:
print
self
.
help
return
course_key
=
None
# parse out the course id into a coursekey
try
:
course_key
=
CourseKey
.
from_string
(
course_id
)
# if it's not a new-style course key, parse it from an old-style
# course key
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
course
=
get_course_by_id
(
course_
id
)
course
=
get_course_by_id
(
course_
key
)
except
Exception
as
err
:
if
course_id
in
modulestore
()
.
courses
:
course
=
modulestore
()
.
courses
[
course_id
]
else
:
print
"-----------------------------------------------------------------------------"
print
"Sorry, cannot find course
%
s"
%
course_id
print
"Please provide a course ID or course data directory name, eg content-mit-801rq"
return
print
"-----------------------------------------------------------------------------"
print
"Sorry, cannot find course with id {}"
.
format
(
course_id
)
print
"Got exception {}"
.
format
(
err
)
print
"Please provide a course ID or course data directory name, eg content-mit-801rq"
return
print
"-----------------------------------------------------------------------------"
print
"Computing grades for
%
s"
%
(
course
.
id
)
print
"Computing grades for
{}"
.
format
(
course_
id
)
offline_grade_calculation
(
course
.
id
)
offline_grade_calculation
(
course
_key
)
lms/djangoapps/instructor/management/commands/dump_grades.py
View file @
9dc48c00
...
...
@@ -7,6 +7,9 @@ import csv
from
instructor.views.legacy
import
get_student_grade_summary_data
from
courseware.courses
import
get_course_by_id
from
opaque_keys
import
InvalidKeyError
from
xmodule.modulestore.keys
import
CourseKey
from
xmodule.modulestore.locations
import
SlashSeparatedCourseKey
from
xmodule.modulestore.django
import
modulestore
from
django.core.management.base
import
BaseCommand
...
...
@@ -39,20 +42,26 @@ class Command(BaseCommand):
get_raw_scores
=
args
[
2
]
.
lower
()
==
'raw'
request
=
DummyRequest
()
# parse out the course into a coursekey
try
:
course
=
get_course_by_id
(
course_id
)
except
Exception
:
if
course_id
in
modulestore
()
.
courses
:
course
=
modulestore
()
.
courses
[
course_id
]
else
:
print
"-----------------------------------------------------------------------------"
print
"Sorry, cannot find course
%
s"
%
course_id
print
"Please provide a course ID or course data directory name, eg content-mit-801rq"
return
course_key
=
CourseKey
.
from_string
(
course_id
)
# if it's not a new-style course key, parse it from an old-style
# course key
except
InvalidKeyError
:
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
course
=
get_course_by_id
(
course_key
)
except
Exception
as
err
:
print
"-----------------------------------------------------------------------------"
print
"Sorry, cannot find course with id {}"
.
format
(
course_id
)
print
"Got exception {}"
.
format
(
err
)
print
"Please provide a course ID or course data directory name, eg content-mit-801rq"
return
print
"-----------------------------------------------------------------------------"
print
"Dumping grades from
%
s to file
%
s (get_raw_scores=
%
s)"
%
(
course
.
id
,
fn
,
get_raw_scores
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course
.
id
,
get_raw_scores
=
get_raw_scores
)
print
"Dumping grades from
{} to file {} (get_raw_scores={})"
.
format
(
course
.
id
,
fn
,
get_raw_scores
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
get_raw_scores
=
get_raw_scores
)
fp
=
open
(
fn
,
'w'
)
...
...
@@ -63,4 +72,4 @@ class Command(BaseCommand):
writer
.
writerow
(
encoded_row
)
fp
.
close
()
print
"Done:
%
d records dumped"
%
len
(
datatable
[
'data'
]
)
print
"Done:
{} records dumped"
.
format
(
len
(
datatable
[
'data'
])
)
lms/djangoapps/instructor/offline_gradecalc.py
View file @
9dc48c00
...
...
@@ -26,21 +26,21 @@ class MyEncoder(JSONEncoder):
yield
chunk
def
offline_grade_calculation
(
course_
id
):
def
offline_grade_calculation
(
course_
key
):
'''
Compute grades for all students for a specified course, and save results to the DB.
'''
tstart
=
time
.
time
()
enrolled_students
=
User
.
objects
.
filter
(
courseenrollment__course_id
=
course_
id
,
courseenrollment__course_id
=
course_
key
,
courseenrollment__is_active
=
1
)
.
prefetch_related
(
"groups"
)
.
order_by
(
'username'
)
enc
=
MyEncoder
()
print
"
%
d enrolled students"
%
len
(
enrolled_students
)
course
=
get_course_by_id
(
course_
id
)
print
"
{} enrolled students"
.
format
(
len
(
enrolled_students
)
)
course
=
get_course_by_id
(
course_
key
)
for
student
in
enrolled_students
:
request
=
DummyRequest
()
...
...
@@ -49,7 +49,7 @@ def offline_grade_calculation(course_id):
gradeset
=
grades
.
grade
(
student
,
request
,
course
,
keep_raw_scores
=
True
)
gs
=
enc
.
encode
(
gradeset
)
ocg
,
created
=
models
.
OfflineComputedGrade
.
objects
.
get_or_create
(
user
=
student
,
course_id
=
course_
id
)
ocg
,
created
=
models
.
OfflineComputedGrade
.
objects
.
get_or_create
(
user
=
student
,
course_id
=
course_
key
)
ocg
.
gradeset
=
gs
ocg
.
save
()
print
"
%
s done"
%
student
# print statement used because this is run by a management command
...
...
@@ -57,18 +57,18 @@ def offline_grade_calculation(course_id):
tend
=
time
.
time
()
dt
=
tend
-
tstart
ocgl
=
models
.
OfflineComputedGradeLog
(
course_id
=
course_
id
,
seconds
=
dt
,
nstudents
=
len
(
enrolled_students
))
ocgl
=
models
.
OfflineComputedGradeLog
(
course_id
=
course_
key
,
seconds
=
dt
,
nstudents
=
len
(
enrolled_students
))
ocgl
.
save
()
print
ocgl
print
"All Done!"
def
offline_grades_available
(
course_
id
):
def
offline_grades_available
(
course_
key
):
'''
Returns False if no offline grades available for specified course.
Otherwise returns latest log field entry about the available pre-computed grades.
'''
ocgl
=
models
.
OfflineComputedGradeLog
.
objects
.
filter
(
course_id
=
course_
id
)
ocgl
=
models
.
OfflineComputedGradeLog
.
objects
.
filter
(
course_id
=
course_
key
)
if
not
ocgl
:
return
False
return
ocgl
.
latest
(
'created'
)
...
...
@@ -86,7 +86,10 @@ def student_grades(student, request, course, keep_raw_scores=False, use_offline=
try
:
ocg
=
models
.
OfflineComputedGrade
.
objects
.
get
(
user
=
student
,
course_id
=
course
.
id
)
except
models
.
OfflineComputedGrade
.
DoesNotExist
:
return
dict
(
raw_scores
=
[],
section_breakdown
=
[],
msg
=
'Error: no offline gradeset available for
%
s,
%
s'
%
(
student
,
course
.
id
))
return
dict
(
raw_scores
=
[],
section_breakdown
=
[],
msg
=
'Error: no offline gradeset available for {}, {}'
.
format
(
student
,
course
.
id
)
)
return
json
.
loads
(
ocg
.
gradeset
)
lms/djangoapps/instructor/views/legacy.py
View file @
9dc48c00
...
...
@@ -226,19 +226,19 @@ def instructor_dashboard(request, course_id):
if
action
==
'Dump list of enrolled students'
or
action
==
'List enrolled students'
:
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
False
,
use_offline
=
use_offline
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
False
,
use_offline
=
use_offline
)
datatable
[
'title'
]
=
_
(
'List of students enrolled in {course_key}'
)
.
format
(
course_key
=
course_key
.
to_deprecated_string
())
track
.
views
.
server_track
(
request
,
"list-students"
,
{},
page
=
"idashboard"
)
elif
'Dump Grades'
in
action
:
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
True
,
use_offline
=
use_offline
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
True
,
use_offline
=
use_offline
)
datatable
[
'title'
]
=
_
(
'Summary Grades of students enrolled in {course_key}'
)
.
format
(
course_key
=
course_key
.
to_deprecated_string
())
track
.
views
.
server_track
(
request
,
"dump-grades"
,
{},
page
=
"idashboard"
)
elif
'Dump all RAW grades'
in
action
:
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
True
,
datatable
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
True
,
get_raw_scores
=
True
,
use_offline
=
use_offline
)
datatable
[
'title'
]
=
_
(
'Raw Grades of students enrolled in {course_key}'
)
.
format
(
course_key
=
course_key
)
track
.
views
.
server_track
(
request
,
"dump-grades-raw"
,
{},
page
=
"idashboard"
)
...
...
@@ -246,12 +246,12 @@ def instructor_dashboard(request, course_id):
elif
'Download CSV of all student grades'
in
action
:
track
.
views
.
server_track
(
request
,
"dump-grades-csv"
,
{},
page
=
"idashboard"
)
return
return_csv
(
'grades_{0}.csv'
.
format
(
course_key
.
to_deprecated_string
()),
get_student_grade_summary_data
(
request
,
course
,
course_key
,
use_offline
=
use_offline
))
get_student_grade_summary_data
(
request
,
course
,
use_offline
=
use_offline
))
elif
'Download CSV of all RAW grades'
in
action
:
track
.
views
.
server_track
(
request
,
"dump-grades-csv-raw"
,
{},
page
=
"idashboard"
)
return
return_csv
(
'grades_{0}_raw.csv'
.
format
(
course_key
.
to_deprecated_string
()),
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_raw_scores
=
True
,
use_offline
=
use_offline
))
get_student_grade_summary_data
(
request
,
course
,
get_raw_scores
=
True
,
use_offline
=
use_offline
))
elif
'Download CSV of answer distributions'
in
action
:
track
.
views
.
server_track
(
request
,
"dump-answer-dist-csv"
,
{},
page
=
"idashboard"
)
...
...
@@ -539,7 +539,7 @@ def instructor_dashboard(request, course_id):
elif
action
==
'List assignments available for this course'
:
log
.
debug
(
action
)
allgrades
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
True
,
use_offline
=
use_offline
)
allgrades
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
True
,
use_offline
=
use_offline
)
assignments
=
[[
x
]
for
x
in
allgrades
[
'assignments'
]]
datatable
=
{
'header'
:
[
_
(
'Assignment Name'
)]}
...
...
@@ -549,7 +549,7 @@ def instructor_dashboard(request, course_id):
msg
+=
'assignments=<pre>
%
s</pre>'
%
assignments
elif
action
==
'List enrolled students matching remote gradebook'
:
stud_data
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
False
,
use_offline
=
use_offline
)
stud_data
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
False
,
use_offline
=
use_offline
)
msg2
,
rg_stud_data
=
_do_remote_gradebook
(
request
.
user
,
course
,
'get-membership'
)
datatable
=
{
'header'
:
[
'Student email'
,
'Match?'
]}
rg_students
=
[
x
[
'email'
]
for
x
in
rg_stud_data
[
'retdata'
]]
...
...
@@ -568,7 +568,7 @@ def instructor_dashboard(request, course_id):
if
not
aname
:
msg
+=
"<font color='red'>{text}</font>"
.
format
(
text
=
_
(
"Please enter an assignment name"
))
else
:
allgrades
=
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
True
,
use_offline
=
use_offline
)
allgrades
=
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
True
,
use_offline
=
use_offline
)
if
aname
not
in
allgrades
[
'assignments'
]:
msg
+=
"<font color='red'>{text}</font>"
.
format
(
text
=
_
(
"Invalid assignment name '{name}'"
)
.
format
(
name
=
aname
)
...
...
@@ -1354,8 +1354,8 @@ class GradeTable(object):
return
self
.
components
.
keys
()
def
get_student_grade_summary_data
(
request
,
course
,
course_key
,
get_grades
=
True
,
get_raw_scores
=
False
,
use_offline
=
False
):
'''
def
get_student_grade_summary_data
(
request
,
course
,
get_grades
=
True
,
get_raw_scores
=
False
,
use_offline
=
False
):
"""
Return data arrays with student identity and grades for specified course.
course = CourseDescriptor
...
...
@@ -1370,8 +1370,8 @@ def get_student_grade_summary_data(request, course, course_key, get_grades=True,
data = list (one per student) of lists of data corresponding to the fields
If get_raw_scores=True, then instead of grade summaries, the raw grades for all graded modules are returned.
'''
"""
course_key
=
course
.
id
enrolled_students
=
User
.
objects
.
filter
(
courseenrollment__course_id
=
course_key
,
courseenrollment__is_active
=
1
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment