From 8d14bab00d822cbf53707971c9f1758df6ae5ac3 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Tue, 8 Mar 2016 10:05:35 -0500 Subject: [PATCH] Use score summaries in data download The submissions API has a get_score() method which, given a student item, will look up the relevant ScoreSummary and return the latest Score it contains. Our data download should do the same. To avoid confusion, we have elected to hide scores that could not be returned from api.get_score(). The other options are: - include a score that may be for a different submission for the same student item, if using ScoreSummary.latest in all cases - include scores that may not "count", because they'll never be the return value of api.get_score() Test has been updated. --- submissions/api.py | 30 +++++++++++++++--------------- submissions/tests/test_api.py | 6 ++++-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/submissions/api.py b/submissions/api.py index 914c3278..0467ef95 100644 --- a/submissions/api.py +++ b/submissions/api.py @@ -447,27 +447,27 @@ def get_all_course_submission_information(course_id, item_type, read_replica=Tru if read_replica: submission_qs = _use_read_replica(submission_qs) - query = submission_qs.select_related('student_item').prefetch_related('score_set').filter( + 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 - if submission.score_set.count() > 0: - for score in submission.score_set.all(): - yield ( - StudentItemSerializer(student_item).data, - SubmissionSerializer(submission).data, - ScoreSerializer(score).data - ) - else: - # Make sure we return submission information even if there isn't a score associated with it. - yield ( - StudentItemSerializer(student_item).data, - SubmissionSerializer(submission).data, - {} - ) + serialized_score = {} + if hasattr(student_item, 'scoresummary'): + latest_score = student_item.scoresummary.latest + + # We only include the score for a given submission if it is not a reset score and it "counts", that is, + # if it is the latest score on the score summary tracking the submission's student_item. 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): diff --git a/submissions/tests/test_api.py b/submissions/tests/test_api.py index 8a5a2b38..5d69da8f 100644 --- a/submissions/tests/test_api.py +++ b/submissions/tests/test_api.py @@ -127,7 +127,8 @@ def test_get_course_submissions(self): 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._assert_score(submissions_and_scores[1][2], 3, 4) + # submission4 also pertains to this student item and got its score later, so no score will be reported here + self.assertEqual(submissions_and_scores[1][2], {}) self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[2][0]) self._assert_submission(submissions_and_scores[2][1], submission2['answer'], student_item1.pk, 2) @@ -135,7 +136,8 @@ def test_get_course_submissions(self): self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[3][0]) self._assert_submission(submissions_and_scores[3][1], submission1['answer'], student_item1.pk, 1) - self._assert_score(submissions_and_scores[3][2], 1, 4) + # submission2 also pertains to this student item and got its score later, so no score will be reported here + self.assertEqual(submissions_and_scores[3][2], {}) def test_get_submission(self): # Test base case that we can create a submission and get it back