build the real curriculum from the textbook structure
تا پیش از این کلِ محتوای دیتابیس ردیفهای [DEMO] و [SEED] بود — دانشآموزِ
پایه نهم در دمو «جمع تا ۱۰» میدید. سینیور «یک بیسیکِ کامل با دیتای واقعی»
خواسته بود.
seed_curriculum_from_textbook (رایگان، هیچ فراخوانیِ پولی ندارد):
Grade ← پایهی کتاب
Unit ← فصلِ کتاب
Node ← درسِ داخلِ فصل، از فهرستِ خودِ کتاب
Lesson ← نوعِ مسئلهی استخراجشده در بازهی صفحهی همان درس
intro_text مستقیم از generalSolution کتاب میآید.
generate_questions_from_chunks سوالِ چهارگزینهای با گزینههای انحرافیِ
باورپذیر میسازد (هزینهدار، اعتبارسنجیِ سختگیرانه). سوال اینجا جدا شد
چون ساختنِ گزینهی انحرافیِ درست به مدل نیاز دارد.
purge_demo_data ردیفهای [SEED]/[DEMO] را گزارش و — فقط با --apply — پاک
میکند؛ بدونِ آن این ردیفها در دمو داخلِ API دیده میشوند.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
87
content/management/commands/purge_demo_data.py
Normal file
87
content/management/commands/purge_demo_data.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
پاککردنِ ردیفهای نمونهی «[SEED]» و «[DEMO]» از دیتابیسِ محلی.
|
||||
|
||||
چرا لازم است: این ردیفها در APIهای واقعی دیده میشوند — «[DEMO] پایهٔ نمونه»
|
||||
در `/api/grades`، «[SEED] ماهانه» در پلنها، «[SEED] کاربر اصلی» در لیدربورد —
|
||||
و در دمو کنارِ محتوای واقعیِ کتاب بد به نظر میرسند.
|
||||
|
||||
برگشتپذیر است: `python manage.py seed_test_data` دوباره میسازدشان.
|
||||
|
||||
python manage.py purge_demo_data # فقط نشان میدهد
|
||||
python manage.py purge_demo_data --apply # واقعاً پاک میکند
|
||||
"""
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
|
||||
PREFIXES = ('[SEED]', '[DEMO]')
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'پاککردنِ ردیفهای نمونهی [SEED]/[DEMO] (برگشتپذیر با seed_test_data).'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--apply', action='store_true',
|
||||
help='بدونِ این فقط گزارش میدهد و چیزی پاک نمیکند.')
|
||||
|
||||
def handle(self, *args, **opts):
|
||||
from accounts.models import User
|
||||
from content.models import Grade
|
||||
from progress.models import Character
|
||||
from subscription.models import Plan
|
||||
|
||||
# (مدل، نامِ فیلدِ متنی) — همهی جاهایی که seed_test_data برچسب میزند.
|
||||
targets = [
|
||||
(Grade, 'title'), (Plan, 'title'), (Character, 'name'), (User, 'name'),
|
||||
]
|
||||
|
||||
found = []
|
||||
for model, field in targets:
|
||||
queryset = model.objects.none()
|
||||
for prefix in PREFIXES:
|
||||
queryset = queryset | model.objects.filter(**{f'{field}__startswith': prefix})
|
||||
rows = list(queryset.distinct())
|
||||
if rows:
|
||||
found.append((model, field, rows))
|
||||
|
||||
if not found:
|
||||
self.stdout.write(self.style.SUCCESS('هیچ ردیفِ نمونهای پیدا نشد.'))
|
||||
return
|
||||
|
||||
self.stdout.write(self.style.MIGRATE_HEADING('\nردیفهای نمونه\n'))
|
||||
total = 0
|
||||
for model, field, rows in found:
|
||||
self.stdout.write(f' {model.__name__} — {len(rows)} ردیف')
|
||||
for row in rows[:8]:
|
||||
self.stdout.write(f' #{row.pk} {getattr(row, field)}')
|
||||
if len(rows) > 8:
|
||||
self.stdout.write(f' … و {len(rows) - 8} مورد دیگر')
|
||||
total += len(rows)
|
||||
|
||||
# هشدارِ لازم: بعضی از اینها تنها دادهٔ آن endpoint هستند.
|
||||
empties = [
|
||||
name for model, name in ((Plan, 'subscription/plans'), (Character, 'characters'))
|
||||
if model.objects.count() == len([r for m, _f, rows in found if m is model for r in rows])
|
||||
]
|
||||
if empties:
|
||||
self.stdout.write(self.style.WARNING(
|
||||
'\n⚠ بعد از پاککردن این endpointها خالی میشوند: ' + '، '.join(empties)
|
||||
+ '\n (پلن و کاراکتر را ادمین در جنگو-ادمین میسازد؛ اگر برای دمو '
|
||||
'لازماند، اول واقعیشان را بساز بعد این را اجرا کن.)'
|
||||
))
|
||||
|
||||
if not opts['apply']:
|
||||
self.stdout.write(self.style.WARNING(
|
||||
f'\n{total} ردیف. چیزی پاک نشد — برای پاککردن --apply بدهید.'
|
||||
))
|
||||
return
|
||||
|
||||
# حذفِ آبشاری: Grade کلِ زیردرختِ Unit/Node/Lesson/Question را میبرد،
|
||||
# و User سشنها و پاسخهایش را. همهشان دادهٔ نمونهاند.
|
||||
with transaction.atomic():
|
||||
for model, _field, rows in found:
|
||||
model.objects.filter(pk__in=[r.pk for r in rows]).delete()
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f'\n{total} ردیفِ نمونه پاک شد.'))
|
||||
self.stdout.write(self.style.HTTP_INFO(
|
||||
'برای برگرداندن: python manage.py seed_test_data'
|
||||
))
|
||||
Reference in New Issue
Block a user