Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: bulk create on mysql #303

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions edx_exams/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -873,12 +873,7 @@ def post(self, request, course_id):
data={'detail': 'Exam does not exist'}
)

StudentAllowance.objects.bulk_create(
allowance_objects,
update_conflicts=True,
unique_fields=['user', 'exam'],
update_fields=['extra_time_mins']
)
StudentAllowance.bulk_create_or_update(allowance_objects)

return Response(status=status.HTTP_200_OK)
else:
Expand Down
22 changes: 21 additions & 1 deletion edx_exams/apps/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ObjectDoesNotExist
from django.db import models, transaction
from django.db import connection, models, transaction
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from model_utils.models import TimeStampedModel
Expand Down Expand Up @@ -454,6 +454,26 @@ class Meta:
verbose_name = 'student allowance'
unique_together = ('user', 'exam')

@classmethod
def bulk_create_or_update(cls, allowances):
"""
Create or update multiple allowances.

SQLite and Postgres have an additional requirement for bulk_create
when using update_conflicts=True. This app expects to run on MySQL
however our tests run on SQLite where 'unique_fields' is needed.
"""
unique_fields = None
if connection.features.supports_update_conflicts_with_target:
unique_fields = ['user', 'exam']

cls.objects.bulk_create(
allowances,
update_conflicts=True,
unique_fields=unique_fields,
update_fields=['extra_time_mins'],
)

@classmethod
def get_allowances_for_course(cls, course_id):
"""
Expand Down
18 changes: 18 additions & 0 deletions edx_exams/apps/core/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,24 @@ def setUp(self):
self.course_id = 'course-v1:edX+Test+Test_Course'
self.exam = ExamFactory(course_id=self.course_id)

def test_bulk_create_or_update(self):
"""
Test bulk_create_or_update can create new allowances and update existing ones.
"""
conflict_user = UserFactory()
conflict_allowance = StudentAllowanceFactory(user=conflict_user, exam=self.exam, extra_time_mins=66)
allowances = [
StudentAllowance(user=conflict_user, exam=self.exam, extra_time_mins=19),
StudentAllowance(user=UserFactory(), exam=self.exam, extra_time_mins=29),
StudentAllowance(user=UserFactory(), exam=self.exam, extra_time_mins=39),
]

self.assertEqual(StudentAllowance.objects.count(), 1)
StudentAllowance.bulk_create_or_update(allowances)
self.assertEqual(StudentAllowance.objects.count(), 3)
conflict_allowance.refresh_from_db()
self.assertEqual(conflict_allowance.extra_time_mins, 19)

def test_get_allowance_for_user(self):
user = UserFactory()
user_2 = UserFactory()
Expand Down
Loading