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.
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 ↗The code
The full code this deep dive walks through — copy the patterns into your own project.
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'),
] from django_fusion.routes import ModelViewset
class EnrollmentViewset(ModelViewset):
model = Enrollment
fields = ['id', 'course', 'user', 'progress', 'completed_at'] Comments
Sign in to join the conversation.
Commenting as