Commit 5350e316 by J. Cliff Dyer

fixup: extract some common code.

parent 0e2534f3
......@@ -16,7 +16,7 @@ from lazy import lazy
import logging
from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db import models
from django.utils.timezone import now
from model_utils.models import TimeStampedModel
......@@ -321,40 +321,36 @@ class PersistentSubsectionGrade(TimeStampedModel):
)
@classmethod
def update_or_create_grade(cls, **kwargs):
def update_or_create_grade(cls, **params):
"""
Wrapper for objects.update_or_create.
"""
cls._prepare_params_and_visible_blocks(kwargs)
user_id = kwargs.pop('user_id')
usage_key = kwargs.pop('usage_key')
attempted = kwargs.pop('attempted')
with transaction.atomic():
grade, _ = cls.objects.update_or_create(
user_id=user_id,
course_id=usage_key.course_key,
usage_key=usage_key,
defaults=kwargs,
)
if attempted and not grade.first_attempted:
grade.first_attempted = now()
grade.save()
grade.full_clean()
cls._prepare_params_and_visible_blocks(params)
user_id = params.pop('user_id')
usage_key = params.pop('usage_key')
attempted = params.pop('attempted')
grade, _ = cls.objects.update_or_create(
user_id=user_id,
course_id=usage_key.course_key,
usage_key=usage_key,
defaults=params,
)
if attempted and not grade.first_attempted:
grade.first_attempted = now()
grade.save()
grade.full_clean()
return grade
@classmethod
def create_grade(cls, **kwargs):
def create_grade(cls, **params):
"""
Wrapper for objects.create.
"""
cls._prepare_params_and_visible_blocks(kwargs)
attempted = kwargs.pop('attempted')
grade = cls(**kwargs)
if attempted:
grade.first_attempted = now()
cls._prepare_params_and_visible_blocks(params)
cls._prepare_attempted_for_create(params, now())
grade = cls(**params)
grade.full_clean()
grade.save()
return grade
......@@ -370,14 +366,13 @@ class PersistentSubsectionGrade(TimeStampedModel):
map(cls._prepare_params, grade_params_iter)
VisibleBlocks.bulk_get_or_create([params['visible_blocks'] for params in grade_params_iter], course_key)
map(cls._prepare_params_visible_blocks_id, grade_params_iter)
first_attempt_timestamp = now()
for params in grade_params_iter:
if params.pop('attempted'):
params['first_attempted'] = first_attempt_timestamp
elif params['earned_all'] != 0.0 or params['earned_graded'] != 0.0:
raise ValidationError("Unattempted problems cannot have a non-zero score.")
return cls.objects.bulk_create([PersistentSubsectionGrade(**params) for params in grade_params_iter])
cls._prepare_attempted_for_create(params, first_attempt_timestamp)
grades = [PersistentSubsectionGrade(**params) for params in grade_params_iter]
for grade in grades:
grade.full_clean()
return cls.objects.bulk_create(grades)
@classmethod
def _prepare_params_and_visible_blocks(cls, params):
......@@ -399,6 +394,15 @@ class PersistentSubsectionGrade(TimeStampedModel):
params['visible_blocks'] = BlockRecordList.from_list(params['visible_blocks'], params['course_id'])
@classmethod
def _prepare_attempted_for_create(cls, params, timestamp):
"""
When creating objects, an attempted subsection gets its timestamp set
unconditionally.
"""
if params.pop('attempted'):
params['first_attempted'] = timestamp
@classmethod
def _prepare_params_visible_blocks_id(cls, params):
"""
Prepares the visible_blocks_id field for the grade record,
......
......@@ -113,7 +113,7 @@ class RecalculateSubsectionGradeTest(ModuleStoreTestCase):
with self.store.default_store(default_store):
self.set_up_course()
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course.id))
with check_mongo_calls(2) and self.assertNumQueries(24 + added_queries):
with check_mongo_calls(2) and self.assertNumQueries(22 + added_queries):
self._apply_recalculate_subsection_grade()
@patch('lms.djangoapps.grades.signals.signals.SUBSECTION_SCORE_CHANGED.send')
......@@ -161,7 +161,7 @@ class RecalculateSubsectionGradeTest(ModuleStoreTestCase):
self.assertTrue(PersistentGradesEnabledFlag.feature_enabled(self.course.id))
ItemFactory.create(parent=self.sequential, category='problem', display_name='problem2')
ItemFactory.create(parent=self.sequential, category='problem', display_name='problem3')
with check_mongo_calls(2) and self.assertNumQueries(24 + added_queries):
with check_mongo_calls(2) and self.assertNumQueries(22 + added_queries):
self._apply_recalculate_subsection_grade()
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
......
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