Commit 68485dd8 by J. Cliff Dyer

Reduce query counts

parent f9d4d6a2
...@@ -14,7 +14,7 @@ from django.db import IntegrityError, DatabaseError ...@@ -14,7 +14,7 @@ from django.db import IntegrityError, DatabaseError
from dogapi import dog_stats_api from dogapi import dog_stats_api
from submissions.serializers import ( from submissions.serializers import (
SubmissionSerializer, StudentItemSerializer, ScoreSerializer SubmissionSerializer, StudentItemSerializer, ScoreSerializer, UnannotatedScoreSerializer
) )
from submissions.models import Submission, StudentItem, Score, ScoreSummary, ScoreAnnotation, score_set, score_reset from submissions.models import Submission, StudentItem, Score, ScoreSummary, ScoreAnnotation, score_set, score_reset
...@@ -626,8 +626,7 @@ def get_score(student_item): ...@@ -626,8 +626,7 @@ def get_score(student_item):
def get_scores(course_id, student_id): def get_scores(course_id, student_id):
""" """Return a dict mapping item_ids -> [ScoreSerializer(ScoreSummary)].
Return a dict mapping item_ids -> [ScoreSerializer(ScoreSummary)].
This method would be used by an LMS to find all the scores for a given This method would be used by an LMS to find all the scores for a given
student in a given course. student in a given course.
...@@ -655,7 +654,7 @@ def get_scores(course_id, student_id): ...@@ -655,7 +654,7 @@ def get_scores(course_id, student_id):
score_summaries = ScoreSummary.objects.filter( score_summaries = ScoreSummary.objects.filter(
student_item__course_id=course_id, student_item__course_id=course_id,
student_item__student_id=student_id, student_item__student_id=student_id,
).select_related('latest', 'student_item') ).select_related('latest', 'latest__submission', 'student_item')
except DatabaseError: except DatabaseError:
msg = u"Could not fetch scores for course {}, student {}".format( msg = u"Could not fetch scores for course {}, student {}".format(
course_id, student_id course_id, student_id
...@@ -663,7 +662,7 @@ def get_scores(course_id, student_id): ...@@ -663,7 +662,7 @@ def get_scores(course_id, student_id):
logger.exception(msg) logger.exception(msg)
raise SubmissionInternalError(msg) raise SubmissionInternalError(msg)
scores = { scores = {
summary.student_item.item_id: ScoreSerializer(summary.latest).data summary.student_item.item_id: UnannotatedScoreSerializer(summary.latest).data
for summary in score_summaries if not summary.latest.is_hidden() for summary in score_summaries if not summary.latest.is_hidden()
} }
return scores return scores
......
...@@ -96,12 +96,31 @@ class ScoreAnnotationSerializer(serializers.ModelSerializer): ...@@ -96,12 +96,31 @@ class ScoreAnnotationSerializer(serializers.ModelSerializer):
) )
class ScoreSerializer(serializers.ModelSerializer): class UnannotatedScoreSerializer(serializers.ModelSerializer):
# Ensure that the created_at datetime is not converted to a string. # Ensure that the created_at datetime is not converted to a string.
created_at = DateTimeField(format=None, required=False) created_at = DateTimeField(format=None, required=False)
class Meta:
model = Score
fields = (
'student_item',
'submission',
'points_earned',
'points_possible',
'created_at',
# Computed
'submission_uuid',
)
class ScoreSerializer(serializers.ModelSerializer):
# Ensure that the created_at datetime is not converted to a string.
created_at = DateTimeField(format=None, required=False)
annotations = serializers.SerializerMethodField() annotations = serializers.SerializerMethodField()
def get_annotations(self, obj): def get_annotations(self, obj):
""" """
Inspect ScoreAnnotations to attach all relevant annotations. Inspect ScoreAnnotations to attach all relevant annotations.
......
...@@ -363,6 +363,7 @@ class TestSubmissionsApi(TestCase): ...@@ -363,6 +363,7 @@ class TestSubmissionsApi(TestCase):
student_item['student_id'] = None student_item['student_id'] = None
self.assertIs(api.get_score(student_item), None) self.assertIs(api.get_score(student_item), None)
@freeze_time(datetime.datetime.now().replace(tzinfo=pytz.UTC))
def test_get_scores(self): def test_get_scores(self):
student_item = copy.deepcopy(STUDENT_ITEM) student_item = copy.deepcopy(STUDENT_ITEM)
student_item["course_id"] = "get_scores_course" student_item["course_id"] = "get_scores_course"
...@@ -388,14 +389,35 @@ class TestSubmissionsApi(TestCase): ...@@ -388,14 +389,35 @@ class TestSubmissionsApi(TestCase):
scores = api.get_scores( scores = api.get_scores(
student_item["course_id"], student_item["student_id"] student_item["course_id"], student_item["student_id"]
) )
self.assertEqual( self.assertEqual(
scores, scores,
{ {
u"i4x://a/b/c/s1": (2, 5), u'i4x://a/b/c/s1': {
u"i4x://a/b/c/s2": (0, 10), 'created_at': datetime.datetime.now(),
u"i4x://a/b/c/s3": (4, 4), 'points_earned': 2,
} 'points_possible': 5,
) 'student_item': 1,
'submission': 1,
'submission_uuid': s1['uuid'],
},
u'i4x://a/b/c/s2': {
'created_at': datetime.datetime.now(),
'points_earned': 0,
'points_possible': 10,
'student_item': 2,
'submission': 2,
'submission_uuid': s2['uuid'],
},
u'i4x://a/b/c/s3': {
'created_at': datetime.datetime.now(),
'points_earned': 4,
'points_possible': 4,
'student_item': 3,
'submission': 3,
'submission_uuid': s3['uuid'],
},
}
)
def test_get_top_submissions(self): def test_get_top_submissions(self):
student_item_1 = copy.deepcopy(STUDENT_ITEM) student_item_1 = copy.deepcopy(STUDENT_ITEM)
......
...@@ -137,7 +137,8 @@ class TestResetScore(TestCase): ...@@ -137,7 +137,8 @@ class TestResetScore(TestCase):
scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'], self.STUDENT_ITEM['student_id']) scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'], self.STUDENT_ITEM['student_id'])
self.assertIn(self.STUDENT_ITEM['item_id'], scores) self.assertIn(self.STUDENT_ITEM['item_id'], scores)
self.assertEqual(scores[self.STUDENT_ITEM['item_id']], (3, 4)) item_score = scores[self.STUDENT_ITEM['item_id']]
self.assertEqual((item_score['points_earned'], item_score['points_possible']), (3, 4))
def test_reset_then_get_score_for_submission(self): def test_reset_then_get_score_for_submission(self):
# Create a submission for the student and score it # Create a submission for the student and score it
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment