Commit 6fa12885 by Diana Huang

Handle IntegrityError according to 1.8 conventions.

parent b8307ca9
...@@ -115,14 +115,15 @@ def on_start(submission_uuid): ...@@ -115,14 +115,15 @@ def on_start(submission_uuid):
""" """
try: try:
submission = sub_api.get_submission_and_student(submission_uuid) with transaction.atomic():
workflow, __ = PeerWorkflow.objects.get_or_create( submission = sub_api.get_submission_and_student(submission_uuid)
student_id=submission['student_item']['student_id'], workflow, __ = PeerWorkflow.objects.get_or_create(
course_id=submission['student_item']['course_id'], student_id=submission['student_item']['student_id'],
item_id=submission['student_item']['item_id'], course_id=submission['student_item']['course_id'],
submission_uuid=submission_uuid item_id=submission['student_item']['item_id'],
) submission_uuid=submission_uuid
workflow.save() )
workflow.save()
except IntegrityError: except IntegrityError:
# If we get an integrity error, it means someone else has already # If we get an integrity error, it means someone else has already
# created a workflow for this submission, so we don't need to do anything. # created a workflow for this submission, so we don't need to do anything.
...@@ -721,14 +722,15 @@ def create_peer_workflow(submission_uuid): ...@@ -721,14 +722,15 @@ def create_peer_workflow(submission_uuid):
""" """
try: try:
submission = sub_api.get_submission_and_student(submission_uuid) with transaction.atomic():
workflow, __ = PeerWorkflow.objects.get_or_create( submission = sub_api.get_submission_and_student(submission_uuid)
student_id=submission['student_item']['student_id'], workflow, __ = PeerWorkflow.objects.get_or_create(
course_id=submission['student_item']['course_id'], student_id=submission['student_item']['student_id'],
item_id=submission['student_item']['item_id'], course_id=submission['student_item']['course_id'],
submission_uuid=submission_uuid item_id=submission['student_item']['item_id'],
) submission_uuid=submission_uuid
workflow.save() )
workflow.save()
except IntegrityError: except IntegrityError:
# If we get an integrity error, it means someone else has already # If we get an integrity error, it means someone else has already
# created a workflow for this submission, so we don't need to do anything. # created a workflow for this submission, so we don't need to do anything.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Public interface for staff grading, used by students/course staff. Public interface for staff grading, used by students/course staff.
""" """
import logging import logging
from django.db import DatabaseError, IntegrityError, transaction from django.db import DatabaseError, transaction
from django.utils.timezone import now from django.utils.timezone import now
from dogapi import dog_stats_api from dogapi import dog_stats_api
......
""" """
Django models specific to the student training assessment type. Django models specific to the student training assessment type.
""" """
from django.db import models, IntegrityError from django.db import models, transaction, IntegrityError
from django.utils import timezone from django.utils import timezone
from submissions import api as sub_api from submissions import api as sub_api
from .training import TrainingExample from .training import TrainingExample
...@@ -137,11 +137,12 @@ class StudentTrainingWorkflow(models.Model): ...@@ -137,11 +137,12 @@ class StudentTrainingWorkflow(models.Model):
next_example = available_examples[0] next_example = available_examples[0]
try: try:
StudentTrainingWorkflowItem.objects.create( with transaction.atomic():
workflow=self, StudentTrainingWorkflowItem.objects.create(
order_num=order_num, workflow=self,
training_example=next_example order_num=order_num,
) training_example=next_example
)
# If we get an integrity error, it means we've violated a uniqueness constraint # If we get an integrity error, it means we've violated a uniqueness constraint
# (someone has created this object after we checked if it existed) # (someone has created this object after we checked if it existed)
# Since the object already exists, we don't need to do anything # Since the object already exists, we don't need to do anything
......
...@@ -181,9 +181,10 @@ def deserialize_training_examples(examples, rubric_dict): ...@@ -181,9 +181,10 @@ def deserialize_training_examples(examples, rubric_dict):
example = TrainingExample.objects.get(content_hash=content_hash) example = TrainingExample.objects.get(content_hash=content_hash)
except TrainingExample.DoesNotExist: except TrainingExample.DoesNotExist:
try: try:
example = TrainingExample.create_example( with transaction.atomic():
example_dict['answer'], example_dict['options_selected'], rubric example = TrainingExample.create_example(
) example_dict['answer'], example_dict['options_selected'], rubric
)
except IntegrityError: except IntegrityError:
example = TrainingExample.objects.get(content_hash=content_hash) example = TrainingExample.objects.get(content_hash=content_hash)
......
...@@ -103,7 +103,7 @@ class StudentTrainingAssessmentTest(CacheResetTest): ...@@ -103,7 +103,7 @@ class StudentTrainingAssessmentTest(CacheResetTest):
# This will need to create the student training workflow and the first item # This will need to create the student training workflow and the first item
# NOTE: we *could* cache the rubric model to reduce the number of queries here, # NOTE: we *could* cache the rubric model to reduce the number of queries here,
# but we're selecting it by content hash, which is indexed and should be plenty fast. # but we're selecting it by content hash, which is indexed and should be plenty fast.
with self.assertNumQueries(6): with self.assertNumQueries(8):
training_api.get_training_example(self.submission_uuid, RUBRIC, EXAMPLES) training_api.get_training_example(self.submission_uuid, RUBRIC, EXAMPLES)
# Without assessing the first training example, try to retrieve a training example. # Without assessing the first training example, try to retrieve a training example.
...@@ -117,7 +117,7 @@ class StudentTrainingAssessmentTest(CacheResetTest): ...@@ -117,7 +117,7 @@ class StudentTrainingAssessmentTest(CacheResetTest):
# Retrieve the next training example, which requires us to create # Retrieve the next training example, which requires us to create
# a new workflow item (but not a new workflow). # a new workflow item (but not a new workflow).
with self.assertNumQueries(6): with self.assertNumQueries(8):
training_api.get_training_example(self.submission_uuid, RUBRIC, EXAMPLES) training_api.get_training_example(self.submission_uuid, RUBRIC, EXAMPLES)
def test_submitter_is_finished_num_queries(self): def test_submitter_is_finished_num_queries(self):
......
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