Spaces:
Sleeping
Sleeping
| """Course and Module models for content organization.""" | |
| from datetime import datetime | |
| from enum import Enum as PyEnum | |
| from sqlalchemy import Column, String, Boolean, DateTime, Enum, Text, Integer, ForeignKey | |
| from sqlalchemy.orm import relationship | |
| from uuid import uuid4 | |
| from app.database import Base | |
| class ContentType(str, PyEnum): | |
| PDF = "pdf" | |
| VIDEO = "video" | |
| MARKDOWN = "markdown" | |
| QUIZ = "quiz" | |
| EXTERNAL_LINK = "external_link" | |
| class DifficultyLevel(str, PyEnum): | |
| BEGINNER = "beginner" | |
| INTERMEDIATE = "intermediate" | |
| ADVANCED = "advanced" | |
| class Course(Base): | |
| __tablename__ = "courses" | |
| id = Column(String(36), primary_key=True, default=lambda: str(uuid4())) | |
| title = Column(String(255), nullable=False) | |
| slug = Column(String(255), unique=True, nullable=False, index=True) | |
| description = Column(Text, nullable=True) | |
| thumbnail_url = Column(String(500), nullable=True) | |
| difficulty = Column(Enum(DifficultyLevel), default=DifficultyLevel.BEGINNER) | |
| is_published = Column(Boolean, default=False) | |
| is_featured = Column(Boolean, default=False) | |
| estimated_hours = Column(Integer, default=0) | |
| order_index = Column(Integer, default=0) | |
| # Creator | |
| created_by = Column(String(36), ForeignKey("users.id"), nullable=True) | |
| # Timestamps | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| # Relationships | |
| modules = relationship("Module", back_populates="course", cascade="all, delete-orphan", order_by="Module.order_index") | |
| enrollments = relationship("Enrollment", back_populates="course", cascade="all, delete-orphan") | |
| def __repr__(self): | |
| return f"<Course {self.title}>" | |
| class Module(Base): | |
| __tablename__ = "modules" | |
| id = Column(String(36), primary_key=True, default=lambda: str(uuid4())) | |
| course_id = Column(String(36), ForeignKey("courses.id"), nullable=False) | |
| title = Column(String(255), nullable=False) | |
| description = Column(Text, nullable=True) | |
| order_index = Column(Integer, default=0) | |
| is_published = Column(Boolean, default=False) | |
| # Unlock requirements | |
| prerequisite_module_id = Column(String(36), ForeignKey("modules.id"), nullable=True) | |
| # Timestamps | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| # Relationships | |
| course = relationship("Course", back_populates="modules") | |
| lessons = relationship("Lesson", back_populates="module", cascade="all, delete-orphan", order_by="Lesson.order_index") | |
| prerequisite = relationship("Module", remote_side="Module.id") | |
| def __repr__(self): | |
| return f"<Module {self.title}>" | |
| class Lesson(Base): | |
| __tablename__ = "lessons" | |
| id = Column(String(36), primary_key=True, default=lambda: str(uuid4())) | |
| module_id = Column(String(36), ForeignKey("modules.id"), nullable=False) | |
| title = Column(String(255), nullable=False) | |
| description = Column(Text, nullable=True) | |
| content_type = Column(Enum(ContentType), nullable=False) | |
| content_url = Column(String(500), nullable=True) # File URL or external link | |
| content_text = Column(Text, nullable=True) # For markdown content | |
| duration_minutes = Column(Integer, default=0) | |
| order_index = Column(Integer, default=0) | |
| is_published = Column(Boolean, default=False) | |
| # Vector store reference | |
| vector_namespace = Column(String(255), nullable=True) | |
| # Timestamps | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) | |
| # Relationships | |
| module = relationship("Module", back_populates="lessons") | |
| progress_records = relationship("Progress", back_populates="lesson", cascade="all, delete-orphan") | |
| quizzes = relationship("Quiz", back_populates="lesson", cascade="all, delete-orphan") | |
| def __repr__(self): | |
| return f"<Lesson {self.title}>" | |