Files
MathApp/content/receivers.py
Zareian 8cb1ecb85e Subjects per grade (math, calculus, geometry, stats, discrete), 5 new textbooks, 202 new islands, long islands split, hand-written figures and lesson texts for the new books
- content.Subject + Unit.subject, /api/home?subject=, tutor grounded in the chosen book
- 5 new books ingested; ~1150 hand-written questions, islands named by hand
- node_split: islands over 7 lessons split into parts of <=6 (lesson ids and progress kept)
- Lesson.figures hand-authored and visually checked for 653 lessons of the new books;
  gen_lesson_figures got --subject and survives network errors
- seed files re-exported

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 05:35:18 +03:30

43 lines
2.9 KiB
Python

from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from .models import Grade, Lesson, Node, Question, Subject, Unit, UserAnswer, UserLessonCompletion
from .services import touch_node_progress_on_answer, update_node_progress_on_lesson_completion
@receiver(post_save, sender=UserAnswer, dispatch_uid='content_touch_node_progress_on_answer')
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, 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)
# با هر تغییرِ برنامه‌ی درسی (از ادمین یا seed)، نسخه‌ی کشِ محتوا یک واحد جلو
# می‌رود و همه‌ی کلیدهای content:grades / content:tree را یک‌جا باطل می‌کند.
@receiver(post_save, sender=Grade, dispatch_uid='content_bump_curriculum_grade_save')
@receiver(post_delete, sender=Grade, dispatch_uid='content_bump_curriculum_grade_delete')
@receiver(post_save, sender=Subject, dispatch_uid='content_bump_curriculum_subject_save')
@receiver(post_delete, sender=Subject, dispatch_uid='content_bump_curriculum_subject_delete')
@receiver(post_save, sender=Unit, dispatch_uid='content_bump_curriculum_unit_save')
@receiver(post_delete, sender=Unit, dispatch_uid='content_bump_curriculum_unit_delete')
@receiver(post_save, sender=Node, dispatch_uid='content_bump_curriculum_node_save')
@receiver(post_delete, sender=Node, dispatch_uid='content_bump_curriculum_node_delete')
@receiver(post_save, sender=Lesson, dispatch_uid='content_bump_curriculum_lesson_save')
@receiver(post_delete, sender=Lesson, dispatch_uid='content_bump_curriculum_lesson_delete')
# سوال هم: نقشه فقط درس‌های سوال‌دار را برای تمام شدنِ جزیره می‌شمارد، پس
# اولین سوالِ یک درس (از ادمین یا import) باید نقشه‌ی کش‌شده را باطل کند.
@receiver(post_save, sender=Question, dispatch_uid='content_bump_curriculum_question_save')
@receiver(post_delete, sender=Question, dispatch_uid='content_bump_curriculum_question_delete')
def _bump_curriculum_cache_version(sender, **kwargs):
from .views import bump_curriculum_version
bump_curriculum_version()