Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-submissions
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-submissions
Commits
ee08c5af
Commit
ee08c5af
authored
Mar 10, 2016
by
Eric Fischer
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #41 from edx/diana/all-submissions
Create new get_all_course_submission_information endpoint.
parents
48dc2630
a5e721e4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
3 deletions
+107
-3
submissions/api.py
+62
-3
submissions/tests/test_api.py
+45
-0
No files found.
submissions/api.py
View file @
ee08c5af
...
...
@@ -10,7 +10,7 @@ import json
from
django.conf
import
settings
from
django.core.cache
import
cache
from
django.db
import
IntegrityError
,
DatabaseError
,
transaction
from
django.db
import
IntegrityError
,
DatabaseError
from
dogapi
import
dog_stats_api
from
submissions.serializers
import
(
...
...
@@ -220,7 +220,7 @@ def get_submission(submission_uuid, read_replica=False):
cache_key
=
Submission
.
get_cache_key
(
submission_uuid
)
try
:
cached_submission_data
=
cache
.
get
(
cache_key
)
except
Exception
as
ex
:
except
Exception
:
# The cache backend could raise an exception
# (for example, memcache keys that contain spaces)
logger
.
exception
(
"Error occurred while retrieving submission from the cache"
)
...
...
@@ -413,6 +413,65 @@ def get_all_submissions(course_id, item_id, item_type, read_replica=True):
yield
data
def
get_all_course_submission_information
(
course_id
,
item_type
,
read_replica
=
True
):
""" For the given course, get all student items of the given item type, all the submissions for those itemes,
and the latest scores for each item. If a submission was given a score that is not the latest score for the
relevant student item, it will still be included but without score.
Args:
course_id (str): The course that we are getting submissions from.
item_type (str): The type of items that we are getting submissions for.
read_replica (bool): Try to use the database's read replica if it's available.
Yields:
A tuple of three dictionaries representing:
(1) a student item with the following fields:
student_id
course_id
student_item
item_type
(2) a submission with the following fields:
student_item
attempt_number
submitted_at
created_at
answer
(3) a score with the following fields, if one exists and it is the latest score:
(if both conditions are not met, an empty dict is returned here)
student_item
submission
points_earned
points_possible
created_at
submission_uuid
"""
submission_qs
=
Submission
.
objects
if
read_replica
:
submission_qs
=
_use_read_replica
(
submission_qs
)
query
=
submission_qs
.
select_related
(
'student_item__scoresummary__latest__submission'
)
.
filter
(
student_item__course_id
=
course_id
,
student_item__item_type
=
item_type
,
)
.
iterator
()
for
submission
in
query
:
student_item
=
submission
.
student_item
serialized_score
=
{}
if
hasattr
(
student_item
,
'scoresummary'
):
latest_score
=
student_item
.
scoresummary
.
latest
# Only include the score if it is not a reset score (is_hidden), and if the current submission is the same
# as the student_item's latest score's submission. This matches the behavior of the API's get_score method.
if
(
not
latest_score
.
is_hidden
())
and
latest_score
.
submission
.
uuid
==
submission
.
uuid
:
serialized_score
=
ScoreSerializer
(
latest_score
)
.
data
yield
(
StudentItemSerializer
(
student_item
)
.
data
,
SubmissionSerializer
(
submission
)
.
data
,
serialized_score
)
def
get_top_submissions
(
course_id
,
item_id
,
item_type
,
number_of_top_scores
,
use_cache
=
True
,
read_replica
=
True
):
"""Get a number of top scores for an assessment based on a particular student item
...
...
@@ -755,7 +814,7 @@ def set_score(submission_uuid, points_earned, points_possible,
u"No submission matching uuid {}"
.
format
(
submission_uuid
)
)
except
DatabaseError
:
error_msg
=
u"Could not retrieve s
tudent item: {} or s
ubmission {}."
.
format
(
error_msg
=
u"Could not retrieve submission {}."
.
format
(
submission_uuid
)
logger
.
exception
(
error_msg
)
...
...
submissions/tests/test_api.py
View file @
ee08c5af
...
...
@@ -101,6 +101,51 @@ class TestSubmissionsApi(TestCase):
self
.
_assert_submission
(
submissions
[
1
],
ANSWER_TWO
,
student_item
.
pk
,
2
)
self
.
assertEqual
(
submissions
[
1
][
'student_id'
],
STUDENT_ITEM
[
'student_id'
])
@ddt.data
(
True
,
False
)
def
test_get_course_submissions
(
self
,
set_scores
):
submission1
=
api
.
create_submission
(
STUDENT_ITEM
,
ANSWER_ONE
)
submission2
=
api
.
create_submission
(
STUDENT_ITEM
,
ANSWER_TWO
)
submission3
=
api
.
create_submission
(
SECOND_STUDENT_ITEM
,
ANSWER_ONE
)
submission4
=
api
.
create_submission
(
SECOND_STUDENT_ITEM
,
ANSWER_TWO
)
if
set_scores
:
api
.
set_score
(
submission1
[
'uuid'
],
1
,
4
)
api
.
set_score
(
submission2
[
'uuid'
],
2
,
4
)
api
.
set_score
(
submission3
[
'uuid'
],
3
,
4
)
api
.
set_score
(
submission4
[
'uuid'
],
4
,
4
)
submissions_and_scores
=
list
(
api
.
get_all_course_submission_information
(
STUDENT_ITEM
[
'course_id'
],
STUDENT_ITEM
[
'item_type'
],
read_replica
=
False
,
))
student_item1
=
self
.
_get_student_item
(
STUDENT_ITEM
)
student_item2
=
self
.
_get_student_item
(
SECOND_STUDENT_ITEM
)
self
.
assertDictEqual
(
SECOND_STUDENT_ITEM
,
submissions_and_scores
[
0
][
0
])
self
.
_assert_submission
(
submissions_and_scores
[
0
][
1
],
submission4
[
'answer'
],
student_item2
.
pk
,
2
)
self
.
assertDictEqual
(
SECOND_STUDENT_ITEM
,
submissions_and_scores
[
1
][
0
])
self
.
_assert_submission
(
submissions_and_scores
[
1
][
1
],
submission3
[
'answer'
],
student_item2
.
pk
,
1
)
self
.
assertDictEqual
(
STUDENT_ITEM
,
submissions_and_scores
[
2
][
0
])
self
.
_assert_submission
(
submissions_and_scores
[
2
][
1
],
submission2
[
'answer'
],
student_item1
.
pk
,
2
)
self
.
assertDictEqual
(
STUDENT_ITEM
,
submissions_and_scores
[
3
][
0
])
self
.
_assert_submission
(
submissions_and_scores
[
3
][
1
],
submission1
[
'answer'
],
student_item1
.
pk
,
1
)
# These scores will always be empty
self
.
assertEqual
(
submissions_and_scores
[
1
][
2
],
{})
self
.
assertEqual
(
submissions_and_scores
[
3
][
2
],
{})
if
set_scores
:
self
.
_assert_score
(
submissions_and_scores
[
0
][
2
],
4
,
4
)
self
.
_assert_score
(
submissions_and_scores
[
2
][
2
],
2
,
4
)
else
:
self
.
assertEqual
(
submissions_and_scores
[
0
][
2
],
{})
self
.
assertEqual
(
submissions_and_scores
[
2
][
2
],
{})
def
test_get_submission
(
self
):
# Test base case that we can create a submission and get it back
sub_dict1
=
api
.
create_submission
(
STUDENT_ITEM
,
ANSWER_ONE
)
...
...
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