Skip to content

Commit f67f96f

Browse files
committed
Ужесточена валидация публикации choice-заданий, синхронизировано поле completed_at со статусом курса и добавлена транзакционная защита от гонок при сохранении single_choice ответа
1 parent 526cace commit f67f96f

3 files changed

Lines changed: 15 additions & 5 deletions

File tree

courses/models/answers.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.conf import settings
22
from django.core.exceptions import ValidationError
3-
from django.db import models
3+
from django.db import models, transaction
44
from django.utils import timezone
55

66
from files.models import UserFile
@@ -203,8 +203,12 @@ def clean(self):
203203
raise ValidationError(errors)
204204

205205
def save(self, *args, **kwargs):
206-
self.full_clean()
207-
super().save(*args, **kwargs)
206+
with transaction.atomic():
207+
if self.answer_id:
208+
# Serializes single_choice writes for one answer.
209+
self.answer.__class__.objects.select_for_update().get(pk=self.answer_id)
210+
self.full_clean()
211+
super().save(*args, **kwargs)
208212

209213

210214
class UserTaskAnswerFile(models.Model):

courses/models/content.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,12 @@ def clean(self):
336336
CourseTaskAnswerType.SINGLE_CHOICE,
337337
CourseTaskAnswerType.MULTIPLE_CHOICE,
338338
)
339-
and self.pk
340339
):
341-
correct_count = self.options.filter(is_correct=True).count()
340+
correct_count = (
341+
self.options.filter(is_correct=True).count()
342+
if self.pk
343+
else 0
344+
)
342345
if correct_count == 0:
343346
errors["status"] = (
344347
"Нельзя опубликовать тестовое задание без правильного варианта."

courses/models/course.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,7 @@ def save(self, *args, **kwargs):
179179
if not self.completed_at:
180180
self.completed_at = timezone.now()
181181

182+
if self.status != CourseContentStatus.COMPLETED:
183+
self.completed_at = None
184+
182185
super().save(*args, **kwargs)

0 commit comments

Comments
 (0)