11 changed files with 430 additions and 13 deletions
-
8apps/lms/admin.py
-
1apps/lms/management/__init__.py
-
1apps/lms/management/commands/__init__.py
-
271apps/lms/management/commands/seed_online_courses.py
-
28apps/lms/migrations/0002_course_adobe_connect_url_course_course_type_and_more.py
-
3apps/lms/models/__init__.py
-
24apps/lms/models/course.py
-
32apps/lms/serializers/course_serializers.py
-
59apps/lms/tests/test_phase8_lms.py
-
8apps/lms/views/course_views.py
-
8apps/profiles/management/commands/seed_almadinah_rich_data.py
@ -0,0 +1 @@ |
|||
# LMS management package |
|||
@ -0,0 +1 @@ |
|||
# LMS management commands |
|||
@ -0,0 +1,271 @@ |
|||
from django.core.management.base import BaseCommand |
|||
from django.contrib.auth import get_user_model |
|||
from apps.profiles.models import Institution |
|||
from apps.lms.models import ( |
|||
Course, |
|||
CourseType, |
|||
CourseCategory, |
|||
CourseLevel, |
|||
CourseLanguage, |
|||
CourseModule, |
|||
Lesson, |
|||
QuizQuestion, |
|||
) |
|||
|
|||
User = get_user_model() |
|||
|
|||
|
|||
class Command(BaseCommand): |
|||
help = "Seeds initial sample online and hybrid courses with Adobe Connect links and live schedules." |
|||
|
|||
def handle(self, *args, **options): |
|||
self.stdout.write(self.style.NOTICE("Seeding sample online courses...")) |
|||
|
|||
admin_user = User.objects.filter(is_staff=True).first() or User.objects.first() |
|||
institution = Institution.objects.first() |
|||
|
|||
sample_courses = [ |
|||
{ |
|||
"title": "Interactive Workshop: International Cultural Diplomacy & Interfaith Dialogue", |
|||
"slug": "online-cultural-diplomacy-interfaith", |
|||
"course_type": CourseType.ONLINE, |
|||
"adobe_connect_url": "https://live.astan.ir/cultural-diplomacy", |
|||
"live_schedule": "Sundays & Tuesdays at 17:00 UTC", |
|||
"category": CourseCategory.CULTURAL_DIPLOMACY, |
|||
"language": CourseLanguage.EN, |
|||
"level": CourseLevel.INTERMEDIATE, |
|||
"instructor_name": "Dr. Mohammad Javad Karimi", |
|||
"instructor_title": "Senior Fellow at Razavi Islamic Studies Institute", |
|||
"organization_name": "Razavi International Academy", |
|||
"description": ( |
|||
"A high-impact live online workshop series exploring strategic communication, " |
|||
"interfaith dialogue methodologies, and cultural diplomacy across global institutions. " |
|||
"All sessions are hosted in real-time via Adobe Connect virtual classroom with interactive Q&A." |
|||
), |
|||
"duration_hours": 16.0, |
|||
"rating": 4.95, |
|||
"reviews_count": 38, |
|||
"is_published": True, |
|||
"is_featured": True, |
|||
"modules": [ |
|||
{ |
|||
"title": "Module 1: Foundations of Cultural Diplomacy", |
|||
"order": 1, |
|||
"lessons": [ |
|||
{ |
|||
"title": "Live Orientation & Syllabus Walkthrough", |
|||
"lesson_type": Lesson.LessonType.READING, |
|||
"duration_minutes": 30, |
|||
"content": ( |
|||
"# Live Course Welcome & Guidelines\n\n" |
|||
"Welcome to the **International Cultural Diplomacy** live series.\n\n" |
|||
"### How to Join the Live Classroom\n" |
|||
"- The live sessions take place every **Sunday and Tuesday at 17:00 UTC**.\n" |
|||
"- Please ensure your Adobe Connect client is updated.\n" |
|||
"- Interactive microphones and webcam access will be enabled during designated Q&A segments." |
|||
), |
|||
"is_preview": True, |
|||
"order": 1, |
|||
}, |
|||
{ |
|||
"title": "Session 1 Live Stream Recording & Summary", |
|||
"lesson_type": Lesson.LessonType.VIDEO, |
|||
"video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", |
|||
"duration_minutes": 60, |
|||
"content": "Archived lecture notes and summary discussion points from the first live lecture.", |
|||
"is_preview": False, |
|||
"order": 2, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
"title": "Module 2: Practical Interfaith Case Studies", |
|||
"order": 2, |
|||
"lessons": [ |
|||
{ |
|||
"title": "Live Workshop: Interfaith Crisis Management", |
|||
"lesson_type": Lesson.LessonType.ASSIGNMENT, |
|||
"duration_minutes": 90, |
|||
"content": "Collaborative case study solving during the live Adobe Connect breakout rooms.", |
|||
"is_preview": False, |
|||
"order": 1, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
"title": "سیره و سبک زندگی رضوی در جامعه معاصر (دوره برخط زنده)", |
|||
"slug": "online-razavi-lifestyle-modern-society", |
|||
"course_type": CourseType.ONLINE, |
|||
"adobe_connect_url": "https://live.astan.ir/razavi-ethics", |
|||
"live_schedule": "پنجشنبهها ساعت ۱۸:۳۰ به وقت تهران", |
|||
"category": CourseCategory.RAZAVI_TEACHINGS, |
|||
"language": CourseLanguage.FA, |
|||
"level": CourseLevel.INTRODUCTORY, |
|||
"instructor_name": "استاد سید علیرضا حسینی", |
|||
"instructor_title": "مدرس حوزه و پژوهشگر سیره و معارف اهلبیت (ع)", |
|||
"organization_name": "مرکز ارتباطات بینالملل آستان قدس رضوی", |
|||
"description": ( |
|||
"دوره تعاملی و برخط پیرامون آموزههای کاربردی امام رضا (ع) در مدیریت خانواده، اخلاق حرفهای، " |
|||
"و مسئولیت اجتماعی در بستر کلاس مجازی ادوبی کانکت با پاسخگویی زنده به پرسشهای دانشجویان." |
|||
), |
|||
"duration_hours": 10.0, |
|||
"rating": 5.0, |
|||
"reviews_count": 64, |
|||
"is_published": True, |
|||
"is_featured": True, |
|||
"modules": [ |
|||
{ |
|||
"title": "فصل اول: مبانی اخلاق گفتوگو و مدارا در سیره امام رضا (ع)", |
|||
"order": 1, |
|||
"lessons": [ |
|||
{ |
|||
"title": "راهنمای ورود به کلاس مجازی ادوبی کانکت و تقویم جلسات", |
|||
"lesson_type": Lesson.LessonType.READING, |
|||
"duration_minutes": 20, |
|||
"content": ( |
|||
"# راهنمای شرکت در جلسات برخط\n\n" |
|||
"دانشپژوهان گرامی، کلاسهای زنده هفتگی از طریق لینک ادوبی کانکت اختصاصی دوره برگزار میگردد.\n" |
|||
"جهت شرکت در مباحث، پس از ورود به سامانه ادوبی، با نام کامل خود وارد اتاق جلسه شوید." |
|||
), |
|||
"is_preview": True, |
|||
"order": 1, |
|||
}, |
|||
{ |
|||
"title": "جلسه زنده اول: مناظرات رضوی و درسهای آن برای دنیای امروز", |
|||
"lesson_type": Lesson.LessonType.READING, |
|||
"duration_minutes": 75, |
|||
"content": "متن و نکات کلیدی جلسه برخط اول همراه با فایل اسلایدها و منابع تکمیلی.", |
|||
"is_preview": False, |
|||
"order": 2, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
"title": "Advanced Islamic Center & Community Leadership (Live Cohort)", |
|||
"slug": "online-center-community-leadership", |
|||
"course_type": CourseType.ONLINE, |
|||
"adobe_connect_url": "https://live.astan.ir/center-leadership", |
|||
"live_schedule": "Every Saturday at 14:00 GMT", |
|||
"category": CourseCategory.CENTER_MANAGEMENT, |
|||
"language": CourseLanguage.EN, |
|||
"level": CourseLevel.ADVANCED, |
|||
"instructor_name": "Sheikh Bilal Al-Kazemi", |
|||
"instructor_title": "Director of International Community Engagement", |
|||
"organization_name": "Federation of Global Islamic Centers", |
|||
"description": ( |
|||
"A specialized leadership masterclass for center directors, mosque trustees, and community organizers. " |
|||
"Features live panel discussions, strategic planning exercises, and real-time governance case studies." |
|||
), |
|||
"duration_hours": 18.0, |
|||
"rating": 4.88, |
|||
"reviews_count": 29, |
|||
"is_published": True, |
|||
"is_featured": False, |
|||
"modules": [ |
|||
{ |
|||
"title": "Module 1: Strategic Governance and Crisis Leadership", |
|||
"order": 1, |
|||
"lessons": [ |
|||
{ |
|||
"title": "Cohort Onboarding & Live Room Setup", |
|||
"lesson_type": Lesson.LessonType.READING, |
|||
"duration_minutes": 25, |
|||
"content": ( |
|||
"# Live Cohort Setup\n\n" |
|||
"Sessions convene every Saturday at 14:00 GMT via Adobe Connect.\n" |
|||
"Please review the community governance code before attending Session 1." |
|||
), |
|||
"is_preview": True, |
|||
"order": 1, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
"title": "Comprehensive Quranic Arabic for Researchers (Hybrid Course)", |
|||
"slug": "hybrid-quranic-arabic-researchers", |
|||
"course_type": CourseType.HYBRID, |
|||
"adobe_connect_url": "https://live.astan.ir/quranic-arabic", |
|||
"live_schedule": "Mondays & Wednesdays at 19:00 Mecca Time", |
|||
"category": CourseCategory.SPECIALIZED_LANGUAGES, |
|||
"language": CourseLanguage.AR, |
|||
"level": CourseLevel.INTERMEDIATE, |
|||
"instructor_name": "د. طارق الهاشمي", |
|||
"instructor_title": "أستاذ اللغويات والترجمة التخصصية", |
|||
"organization_name": "معهد الدراسات اللغوية التخصصية", |
|||
"description": ( |
|||
"دورة هجينة تجمع بين الدروس المسجلة الذاتية وورش العمل الحية الأسبوعية عبر أدوبي كونكت " |
|||
"لتحليل النصوص الدينية والمصطلحات القرآنية التخصصية." |
|||
), |
|||
"duration_hours": 24.0, |
|||
"rating": 4.92, |
|||
"reviews_count": 45, |
|||
"is_published": True, |
|||
"is_featured": True, |
|||
"modules": [ |
|||
{ |
|||
"title": "الوحدة الأولى: البنية الصرفية والنحوية المتقدمة", |
|||
"order": 1, |
|||
"lessons": [ |
|||
{ |
|||
"title": "مقدمة البرنامج وجدول البث المباشر", |
|||
"lesson_type": Lesson.LessonType.READING, |
|||
"duration_minutes": 20, |
|||
"content": ( |
|||
"# جدول الجلسات التفاعلية المباشرة\n\n" |
|||
"تنعقد الورش الحية يومي الإثنين والأربعاء الساعة 19:00 بتوقيت مكة المكرمة عبر قاعة أدوبي كونكت." |
|||
), |
|||
"is_preview": True, |
|||
"order": 1, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
] |
|||
|
|||
created_count = 0 |
|||
for data in sample_courses: |
|||
modules_data = data.pop("modules", []) |
|||
slug = data["slug"] |
|||
|
|||
course, created = Course.objects.update_or_create( |
|||
slug=slug, |
|||
defaults={ |
|||
**data, |
|||
"institution": institution, |
|||
"created_by": admin_user, |
|||
} |
|||
) |
|||
|
|||
if created: |
|||
created_count += 1 |
|||
self.stdout.write(self.style.SUCCESS(f"Created course: {course.title} ({course.course_type})")) |
|||
else: |
|||
self.stdout.write(self.style.WARNING(f"Updated course: {course.title} ({course.course_type})")) |
|||
|
|||
# Create modules and lessons |
|||
for m_data in modules_data: |
|||
lessons_data = m_data.pop("lessons", []) |
|||
module, _ = CourseModule.objects.update_or_create( |
|||
course=course, |
|||
order=m_data["order"], |
|||
defaults={"title": m_data["title"]}, |
|||
) |
|||
for l_data in lessons_data: |
|||
Lesson.objects.update_or_create( |
|||
module=module, |
|||
order=l_data["order"], |
|||
defaults=l_data, |
|||
) |
|||
|
|||
self.stdout.write( |
|||
self.style.SUCCESS( |
|||
f"Successfully seeded {len(sample_courses)} online/hybrid courses (New: {created_count})!" |
|||
) |
|||
) |
|||
@ -0,0 +1,28 @@ |
|||
# Generated by Django 4.2.30 on 2026-10-22 06:59 |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('lms', '0001_initial'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='course', |
|||
name='adobe_connect_url', |
|||
field=models.URLField(blank=True, max_length=500, null=True, verbose_name='Adobe Connect / Online Meeting Link'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='course', |
|||
name='course_type', |
|||
field=models.CharField(choices=[('recorded', 'Recorded / Self-Paced'), ('online', 'Live Online (Adobe Connect)'), ('hybrid', 'Hybrid (Recorded & Live Online)')], default='recorded', max_length=20, verbose_name='Course Delivery Type'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='course', |
|||
name='live_schedule', |
|||
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Live Schedule (e.g. Saturdays at 18:00 UTC)'), |
|||
), |
|||
] |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue