Structa Cloud Structa Cloud

Engineering

The Precis LMS content model

How Precis LMS models courses and enrollments in Wagtail + django-fusion — the content-driven pattern the Loop site builder generalizes.

Engineering 7 min read ← All posts

The learning platform models content the way the CMS does: Wagtail pages plus StreamField blocks. A course is a page with a curriculum; an enrollment is a fusion viewset over that content.

Why pages, not tables

Courses are content — editors should compose lessons and quizzes without a migration. StreamField gives them exactly that, and the frontend consumes the same structure the CMS does.

The viewset

Reads ride django-fusion's ModelViewset: a class, a model and a field list. The enrollment row tracks progress and the completion date; everything else is derived from it.

variants & screenshots

See it in each edition

A screenshot per variant — open any one to jump straight to the live preview.

Course page

A lesson + quiz curriculum composed in a Wagtail StreamField.

See Precis LMS ↗
code sections

The code

The full code this deep dive walks through — copy the patterns into your own project.

Wagtail course page
python
class CoursePage(Page):
    title = models.CharField(max_length=255)
    description = RichTextField(blank=True)
    price_cents = models.IntegerField(default=0)
    curriculum = StreamField([
        ('lesson', LessonBlock()),
        ('quiz', QuizBlock()),
    ], use_json_field=True)

    content_panels = Page.content_panels + [
        FieldPanel('description'),
        FieldPanel('price_cents'),
        FieldPanel('curriculum'),
    ]
Enrollment (django-fusion)
python
from django_fusion.routes import ModelViewset

class EnrollmentViewset(ModelViewset):
    model = Enrollment
    fields = ['id', 'course', 'user', 'progress', 'completed_at']

Comments

A useful first release beats a noisy roadmap

We start with the customer journey, launch a focused slice, and leave your team with the content and tools to keep improving it.

ready when you are · text/html