From ddc6c7c9b72dfb71fa7fbb2ae9b8cca77d3f548b Mon Sep 17 00:00:00 2001 From: Zareian Date: Thu, 8 Oct 2026 11:54:20 +0330 Subject: [PATCH] NodeProgress receivers skip raw saves (loaddata duplicated rows on the Postgres move) Co-Authored-By: Claude Sonnet 5.5 --- content/receivers.py | 10 ++++++---- content/tests_loaddata_raw.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 content/tests_loaddata_raw.py diff --git a/content/receivers.py b/content/receivers.py index 3d4b738..6694e1a 100644 --- a/content/receivers.py +++ b/content/receivers.py @@ -6,15 +6,17 @@ from .services import touch_node_progress_on_answer, update_node_progress_on_les @receiver(post_save, sender=UserAnswer, dispatch_uid='content_touch_node_progress_on_answer') -def _on_user_answer_created(sender, instance, created, **kwargs): - if not created: +def _on_user_answer_created(sender, instance, created, raw=False, **kwargs): + # raw=True: loaddata/dumpdata-انتقال؛ ردیفِ NodeProgress خودش در فایل است و ساختنش اینجا تکراری می‌شد. + if raw or not created: return touch_node_progress_on_answer(instance.user_id, instance.question) @receiver(post_save, sender=UserLessonCompletion, dispatch_uid='content_update_node_progress_on_completion') -def _on_lesson_completion_created(sender, instance, created, **kwargs): - if not created: +def _on_lesson_completion_created(sender, instance, created, raw=False, **kwargs): + # raw=True: loaddata/dumpdata-انتقال؛ ردیفِ NodeProgress خودش در فایل است و ساختنش اینجا تکراری می‌شد. + if raw or not created: return update_node_progress_on_lesson_completion(instance.user_id, instance.lesson) diff --git a/content/tests_loaddata_raw.py b/content/tests_loaddata_raw.py new file mode 100644 index 0000000..15fa41b --- /dev/null +++ b/content/tests_loaddata_raw.py @@ -0,0 +1,18 @@ +"""loaddata (انتقال به Postgres) نباید از روی سیگنال NodeProgress بسازد: خودِ ردیف در فایل است.""" +from django.db.models.signals import post_save +from django.test import TestCase + +from content.models import Choice, Grade, Lesson, Node, NodeProgress, Question, Unit, UserAnswer + + +class RawSaveTests(TestCase): + def test_raw_user_answer_save_creates_no_node_progress(self): + grade = Grade.objects.create(title='g', number=99) + unit = Unit.objects.create(grade=grade, title='u', order=1) + node = Node.objects.create(unit=unit, title='n', order=1) + lesson = Lesson.objects.create(node=node, title='l') + q = Question.objects.create(lesson=lesson, type='multiple_choice', prompt='p') + c = Choice.objects.create(question=q, value='a', is_correct=True) + answer = UserAnswer(user_id=1, question=q, choice=c, correct=True) + post_save.send(UserAnswer, instance=answer, created=True, raw=True) + self.assertEqual(NodeProgress.objects.count(), 0)