Skip to main content

A Learning Management System extension for Wagtail with SCORM 1.2/2004 and H5P support

Project description

Wagtail LMS

CI codecov PyPI version Python 3.11+ License: MIT pre-commit.ci status Documentation Status

A Learning Management System extension for Wagtail CMS with SCORM 1.2/2004 and H5P support.

⚠️ Alpha Release

This package is in early development. That said, it is actively used in production at thinkelearn.com.

Supported versions:

  • Python: 3.11, 3.12, 3.13, 3.14
  • Django: 4.2 (LTS), 5.0, 5.1, 5.2 (LTS), 6.0
  • Wagtail: 6.0, 6.2, 6.3, 7.1, 7.2, 7.3

Selected combinations are tested in CI. See our compatibility matrix for specific version combinations.

Features

  • 📚 Course Management - Integrate courses into Wagtail's page system
  • 📦 SCORM Support - Full SCORM 1.2 and 2004 package compatibility
  • 🎯 H5P Support - Embed interactive H5P activities in long-scroll lesson pages
  • 👥 Enrollment Tracking - Automatic student enrollment and progress monitoring
  • 📊 SCORM API - Complete runtime API implementation for content interactivity
  • 📡 xAPI Tracking - Record H5P learner interactions as xAPI statements
  • 🔒 Secure Delivery - Path-validated content serving with iframe support
  • 💾 Progress Persistence - CMI data model storage with suspend/resume capability
  • 🔄 Concurrency Handling - Retry logic for SQLite database lock scenarios
  • 🎨 Framework Agnostic - Minimal default styling, easy to customize with any CSS framework

Installation

pip install wagtail-lms

Quick Start

  1. Add to INSTALLED_APPS in your Django settings:

    INSTALLED_APPS = [
        # ...
        'wagtail_lms',
        # ...
    ]
    
  2. Add wagtail-lms URLs to your urls.py:

    from django.urls import path, include
    
    urlpatterns = [
        # ...
        path('lms/', include('wagtail_lms.urls')),
        # ...
    ]
    
  3. Run migrations:

    python manage.py migrate wagtail_lms
    
  4. Collect static files:

    python manage.py collectstatic
    

Configuration

Optional settings in your Django settings:

# SCORM
WAGTAIL_LMS_SCORM_UPLOAD_PATH = 'scorm_packages/'  # Upload directory
WAGTAIL_LMS_SCORM_CONTENT_PATH = 'scorm_content/'        # Extracted content
WAGTAIL_LMS_AUTO_ENROLL = False                     # Auto-enroll on course visit

# H5P
WAGTAIL_LMS_H5P_UPLOAD_PATH = 'h5p_packages/'      # Upload directory
WAGTAIL_LMS_H5P_CONTENT_PATH = 'h5p_content/'      # Extracted content

# Cache-Control rules for served assets (exact MIME, wildcard, and default)
WAGTAIL_LMS_CACHE_CONTROL = {
    "text/html": "no-cache",
    "text/css": "max-age=86400",
    "application/javascript": "max-age=86400",
    "text/javascript": "max-age=86400",
    "image/*": "max-age=604800",
    "font/*": "max-age=604800",
    "default": "max-age=86400",
}

# Redirect audio/video assets to storage URLs (useful for S3 backends)
WAGTAIL_LMS_REDIRECT_MEDIA = False

# Use custom Wagtail admin viewsets for upload flows
WAGTAIL_LMS_SCORM_PACKAGE_VIEWSET_CLASS = "wagtail_lms.viewsets.SCORMPackageViewSet"
WAGTAIL_LMS_H5P_ACTIVITY_VIEWSET_CLASS = "wagtail_lms.viewsets.H5PActivityViewSet"
WAGTAIL_LMS_H5P_SNIPPET_VIEWSET_CLASS = "wagtail_lms.viewsets.H5PActivitySnippetViewSet"

# Lesson access hook (dotted-path callable)
WAGTAIL_LMS_CHECK_LESSON_ACCESS = "wagtail_lms.access.default_lesson_access_check"

# Django admin registration controls
WAGTAIL_LMS_REGISTER_DJANGO_ADMIN = True
WAGTAIL_LMS_SCORM_ADMIN_CLASS = "wagtail_lms.admin.SCORMPackageAdmin"
WAGTAIL_LMS_H5P_ADMIN_CLASS = "wagtail_lms.admin.H5PActivityAdmin"

Usage

SCORM Courses

  1. Log into Wagtail admin
  2. Create a new Course Page under Pages
  3. Upload a SCORM package via LMS → SCORM Packages in the Wagtail admin
  4. Assign the SCORM package to your course page and publish

SCORM package requirements:

  • Valid SCORM 1.2 or 2004 ZIP file
  • Must contain imsmanifest.xml at the root
  • Launch file must be specified in the manifest

H5P Lessons

H5P activities are composed into long-scroll Lesson Pages alongside rich text. A lesson is always a child of a Course Page; enrollment in the course is required to access its lessons.

  1. Upload an H5P Activity snippet via LMS → H5P Activities in the Wagtail admin
  2. Create a Course Page (no SCORM package required for H5P-only courses)
  3. Add a Lesson Page as a child of the Course Page
  4. In the lesson body, add H5P Activity blocks (and/or rich text blocks) to compose the lesson
  5. Publish — enrolled learners can access the lesson; xAPI statements are recorded automatically

H5P package requirements:

  • Valid .h5p file (ZIP with an .h5p extension) containing h5p.json at the root

  • Must include library JavaScript files — h5p-standalone renders content using library JS bundled inside the package (e.g. H5P.InteractiveVideo-1.27/). A warning is logged and "Could not load activity." is shown if files are missing.

    • Lumi desktop editor (free, open-source) — recommended
    • ✅ Moodle / WordPress / Drupal H5P plugin export
    • ✅ Lumi Cloud (free tier available at lumi.education)
    • ❌ H5P.org "Reuse" download — content-only, no library files included
    • ❌ H5P.org does not offer a download-with-libraries option for any content

Customizing Templates

The package includes minimal, functional styling that works out of the box. To match your project's design:

  • Quick: Override the CSS classes in your own stylesheet
  • Full control: Override the templates in your project (standard Django approach)
  • Examples: See Template Customization Guide for Bootstrap, Tailwind CSS, and Bulma examples

For API-first projects, the templates are optional and can be ignored entirely.

Development

An example project is available in example_project/ for local development and testing. See its README for setup instructions.

Running Tests

The project includes a comprehensive test suite. See current coverage.

# Install testing dependencies (pytest, pytest-django, pytest-cov)
uv sync --extra testing

# Run all tests
PYTHONPATH=. uv run pytest

# Run with coverage report
PYTHONPATH=. uv run pytest --cov=src/wagtail_lms --cov-report=term-missing

# Run specific test file
PYTHONPATH=. uv run pytest tests/test_models.py -v

Database Considerations

SQLite: The package includes retry logic with exponential backoff to handle database lock errors during concurrent SCORM API operations. For development with the example project:

# example_project/settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": "db.sqlite3",
        "OPTIONS": {
            "timeout": 20,  # Increased timeout for SCORM operations
        },
    }
}

Production: For production deployments, PostgreSQL is recommended for better concurrency handling:

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "wagtail_lms",
        # ... other PostgreSQL settings
    }
}

Acknowledgments

  • Built with Django and Wagtail CMS
  • SCORM implementation based on ADL specifications
  • H5P support powered by H5P and h5p-standalone
  • Lumi — recommended free, open-source H5P editor for creating self-contained packages
  • Inspired by open-source LMS solutions like Moodle and Open edX

License

This project is licensed under the MIT License. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wagtail_lms-0.10.0.tar.gz (618.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wagtail_lms-0.10.0-py3-none-any.whl (652.7 kB view details)

Uploaded Python 3

File details

Details for the file wagtail_lms-0.10.0.tar.gz.

File metadata

  • Download URL: wagtail_lms-0.10.0.tar.gz
  • Upload date:
  • Size: 618.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wagtail_lms-0.10.0.tar.gz
Algorithm Hash digest
SHA256 94f32eecab530ce12214b64041195539979dec5b07ec4b2019b110d322d32fd0
MD5 551e66811ab3c88919634632711f61c1
BLAKE2b-256 5e3e3ed9b42c85c9bd1aeef8f9ffe4a6e61a431154638d7d81fda8d8009dae19

See more details on using hashes here.

Provenance

The following attestation bundles were made for wagtail_lms-0.10.0.tar.gz:

Publisher: publish.yml on dr-rompecabezas/wagtail-lms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wagtail_lms-0.10.0-py3-none-any.whl.

File metadata

  • Download URL: wagtail_lms-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 652.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wagtail_lms-0.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e350df5249497746cdc729dbb1f2edb4f6b3200ec20464c44f7daa02d054510c
MD5 93b2d5a336077d91c85eef4297c9e176
BLAKE2b-256 db5f6a04f09eb2e1d4538cdc2ba939029d2e6c85dadb70d71792d6ff22e2ac65

See more details on using hashes here.

Provenance

The following attestation bundles were made for wagtail_lms-0.10.0-py3-none-any.whl:

Publisher: publish.yml on dr-rompecabezas/wagtail-lms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page