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
d201c06f
Commit
d201c06f
authored
Sep 12, 2014
by
Matt Drayer
Committed by
Jonathan Piacenti
Aug 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mattdrayer/api-course-avg-release: Account for ungraded students
parent
fb28f68f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
32 additions
and
16 deletions
+32
-16
lms/djangoapps/api_manager/courses/tests.py
+6
-2
lms/djangoapps/api_manager/courses/views.py
+5
-9
lms/djangoapps/gradebook/models.py
+21
-5
No files found.
lms/djangoapps/api_manager/courses/tests.py
View file @
d201c06f
...
...
@@ -1573,7 +1573,7 @@ class CoursesApiTests(TestCase):
parent_location
=
self
.
chapter
.
location
,
category
=
'mentoring'
,
data
=
StringResponseXMLFactory
()
.
build_xml
(
answer
=
'foo'
),
display_name
=
u"test problem s
ma
e points"
,
display_name
=
u"test problem s
am
e points"
,
metadata
=
{
'rerandomize'
:
'always'
,
'graded'
:
True
,
'format'
:
"Midterm Exam"
}
)
...
...
@@ -1591,7 +1591,6 @@ class CoursesApiTests(TestCase):
grade_dict
=
{
'value'
:
points_scored
,
'max_value'
:
points_possible
,
'user_id'
:
user
.
id
}
module
.
system
.
publish
(
module
,
'grade'
,
grade_dict
)
StudentGradebook
.
objects
.
filter
(
user
=
user
)
.
update
(
created
=
timezone
.
now
()
-
timedelta
(
days
=
1
))
test_uri
=
'{}/{}/metrics/grades/leaders/'
.
format
(
self
.
base_courses_uri
,
self
.
test_course_id
)
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
...
...
@@ -1615,11 +1614,16 @@ class CoursesApiTests(TestCase):
# Filter by user who has never accessed a course module
test_user
=
UserFactory
.
create
(
username
=
"testusernocoursemod"
)
CourseEnrollmentFactory
.
create
(
user
=
test_user
,
course_id
=
self
.
course
.
id
)
user_filter_uri
=
'{}?user_id={}'
.
format
(
test_uri
,
test_user
.
id
)
response
=
self
.
do_get
(
user_filter_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
data
[
'user_grade'
],
0
)
self
.
assertEqual
(
response
.
data
[
'user_position'
],
6
)
# Also, with this new user now added the course average should be different
self
.
assertNotEqual
(
response
.
data
[
'course_avg'
],
expected_course_average
)
rounded_avg
=
float
(
"{0:.2f}"
.
format
(
response
.
data
[
'course_avg'
]))
self
.
assertEqual
(
rounded_avg
,
0.33
)
# test with bogus course
bogus_test_uri
=
'{}/{}/metrics/grades/leaders/'
.
format
(
self
.
base_courses_uri
,
self
.
test_bogus_course_id
)
...
...
lms/djangoapps/api_manager/courses/views.py
View file @
d201c06f
...
...
@@ -1433,11 +1433,7 @@ class CoursesMetricsGradesList(SecureListAPIView):
queryset_grade_min
=
queryset
.
aggregate
(
Min
(
'grade'
))
queryset_grade_count
=
queryset
.
aggregate
(
Count
(
'grade'
))
course_queryset
=
StudentGradebook
.
objects
.
filter
(
course_id__exact
=
course_key
)
.
exclude
(
user__in
=
exclude_users
)
course_queryset_grade_avg
=
course_queryset
.
aggregate
(
Avg
(
'grade'
))
course_queryset_grade_max
=
course_queryset
.
aggregate
(
Max
(
'grade'
))
course_queryset_grade_min
=
course_queryset
.
aggregate
(
Min
(
'grade'
))
course_queryset_grade_count
=
course_queryset
.
aggregate
(
Count
(
'grade'
))
course_metrics
=
StudentGradebook
.
generate_leaderboard
(
course_key
,
exclude_users
=
exclude_users
)
response_data
=
{}
base_uri
=
generate_base_uri
(
request
)
...
...
@@ -1448,10 +1444,10 @@ class CoursesMetricsGradesList(SecureListAPIView):
response_data
[
'grade_minimum'
]
=
queryset_grade_min
[
'grade__min'
]
response_data
[
'grade_count'
]
=
queryset_grade_count
[
'grade__count'
]
response_data
[
'course_grade_average'
]
=
course_
queryset_grade_avg
[
'grade_
_avg'
]
response_data
[
'course_grade_maximum'
]
=
course_
queryset_grade_max
[
'grade_
_max'
]
response_data
[
'course_grade_minimum'
]
=
course_
queryset_grade_min
[
'grade_
_min'
]
response_data
[
'course_grade_count'
]
=
course_
queryset_grade_count
[
'grade_
_count'
]
response_data
[
'course_grade_average'
]
=
course_
metrics
[
'course
_avg'
]
response_data
[
'course_grade_maximum'
]
=
course_
metrics
[
'course
_max'
]
response_data
[
'course_grade_minimum'
]
=
course_
metrics
[
'course
_min'
]
response_data
[
'course_grade_count'
]
=
course_
metrics
[
'course
_count'
]
response_data
[
'grades'
]
=
[]
for
row
in
queryset
:
...
...
lms/djangoapps/gradebook/models.py
View file @
d201c06f
...
...
@@ -5,11 +5,12 @@ from django.utils import timezone
from
django.contrib.auth.models
import
User
from
django.db
import
models
from
django.db.models
import
Avg
from
django.db.models
import
Avg
,
Max
,
Min
,
Count
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
model_utils.models
import
TimeStampedModel
from
student.models
import
CourseEnrollment
from
xmodule_django.models
import
CourseKeyField
...
...
@@ -48,19 +49,34 @@ class StudentGradebook(TimeStampedModel):
'user_position': 4,
'user_grade': 0.89
}
If there is a discrepancy between the number of gradebook entries and the overall number of enrolled
users (excluding any users who should be excluded), then we modify the course average to account for
those users who currently lack gradebook entries. We assume zero grades for these users because they
have not yet submitted a response to a scored assessment which means no grade has been calculated.
"""
data
=
{}
total_user_count
=
CourseEnrollment
.
users_enrolled_in
(
course_key
)
.
count
()
queryset
=
StudentGradebook
.
objects
.
select_related
(
'user'
)
\
.
filter
(
course_id__exact
=
course_key
,
user__is_active
=
True
)
gradebook_user_count
=
len
(
queryset
)
if
exclude_users
:
total_user_count
=
total_user_count
-
len
(
exclude_users
)
queryset
=
queryset
.
exclude
(
user__in
=
exclude_users
)
gradebook_user_count
=
len
(
queryset
)
# print StudentGradebook.objects.select_related('user')\
# .filter(course_id__exact=course_key, user__is_active=True).query
# assert 0
# Calculate the class average
course_avg
=
queryset
.
aggregate
(
Avg
(
'grade'
))[
'grade__avg'
]
if
gradebook_user_count
<
total_user_count
:
# Take into account any ungraded students (assumes zeros for grades...)
course_avg
=
course_avg
/
total_user_count
*
gradebook_user_count
data
[
'course_avg'
]
=
course_avg
data
[
'course_max'
]
=
queryset
.
aggregate
(
Max
(
'grade'
))[
'grade__max'
]
data
[
'course_min'
]
=
queryset
.
aggregate
(
Min
(
'grade'
))[
'grade__min'
]
data
[
'course_count'
]
=
queryset
.
aggregate
(
Count
(
'grade'
))[
'grade__count'
]
# Construct the leaderboard as a queryset
data
[
'course_avg'
]
=
queryset
.
aggregate
(
Avg
(
'grade'
))[
'grade__avg'
]
data
[
'queryset'
]
=
queryset
.
values
(
'user__id'
,
'user__username'
,
...
...
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