Rework model

This commit is contained in:
Elia Bieri 2023-03-29 15:28:11 +02:00 committed by Daniel Egger
parent 9ecb9a9add
commit 4cf292bbf8
14 changed files with 170 additions and 49 deletions

View File

@ -97,6 +97,7 @@ if [ "$SKIP_SETUP" = false ]; then
echo "python server/manage.py create_default_courses $course_param"
python server/manage.py create_default_courses $course_param
python server/manage.py create_default_notifications
python server/manage.py create_default_assignments
# make django translations
(cd server && python manage.py compilemessages)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class AssignmentConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'assignment'
default_auto_field = "django.db.models.BigAutoField"
name = "vbv_lernwelt.assignment"

View File

@ -0,0 +1,29 @@
from wagtail_factories import StreamFieldFactory
from vbv_lernwelt.assignment.tests.assignment_factories import (
PerformanceObjectiveBlockFactory,
AssignmentPageFactory,
AssignmentFactory,
TaskBlockFactory,
)
from vbv_lernwelt.course.consts import COURSE_UK
from vbv_lernwelt.course.models import CoursePage
def create_assignments():
course_page = CoursePage.objects.get(course_id=COURSE_UK)
assignment_page = AssignmentPageFactory(
parent=course_page,
)
AssignmentFactory(
parent=assignment_page,
title="Auftrag 1",
performance_objectives=StreamFieldFactory(
{
"performance_objective": PerformanceObjectiveBlockFactory(),
}
),
effort_required="1 - 2 Stunden",
assessment_document_url="https://www.vbv.ch",
tasks=StreamFieldFactory({"task": TaskBlockFactory()}),
)

View File

@ -0,0 +1,9 @@
import djclick as click
from vbv_lernwelt.assignment.creators.create_assignments import create_assignments
@click.command()
def command():
print("Creating default assignments")
create_assignments()

View File

@ -1,8 +1,8 @@
# Generated by Django 3.2.13 on 2023-03-28 08:53
# Generated by Django 3.2.13 on 2023-03-30 13:30
import assignment.models
from django.db import migrations, models
import django.db.models.deletion
import vbv_lernwelt.assignment.models
import wagtail.blocks
import wagtail.fields
@ -13,10 +13,24 @@ class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0069_log_entry_jsonfield'),
('files', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Assignment',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
('starting_position', models.TextField()),
('performance_objectives', wagtail.fields.StreamField([('performance_objective', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())]))], use_json_field=True)),
('effort_required', models.TextField()),
('assessment_document_url', models.TextField()),
('tasks', wagtail.fields.StreamField([('task', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock()), ('file_submission_required', wagtail.blocks.BooleanBlock()), ('content', wagtail.blocks.StreamBlock([('explanation', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())])), ('user_text_input', vbv_lernwelt.assignment.models.UserTextInputBlock()), ('user_confirmation', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())]))], use_json_field=True))]))], use_json_field=True)),
],
options={
'verbose_name': 'Auftrag',
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='AssignmentPage',
fields=[
@ -28,19 +42,10 @@ class Migration(migrations.Migration):
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='Assignment',
name='AssignmentSubmission',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
('starting_position', models.CharField(max_length=1024)),
('due', models.DateTimeField()),
('performance_objectives', wagtail.fields.StreamField([('performance_objective', assignment.models.PerformanceObjectiveBlock())], use_json_field=True)),
('effort_required', models.CharField(max_length=255)),
('tasks', wagtail.fields.StreamField([('task', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock()), ('file_submission_required', wagtail.blocks.BooleanBlock()), ('content', wagtail.blocks.StreamBlock([('explanation', assignment.models.ExplanationBlock()), ('user_text_input', assignment.models.UserTextInputBlock()), ('user_confirmation', assignment.models.UserConfirmationBlock())], use_json_field=True))]))], use_json_field=True)),
('assessment_tool', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='files.uploadfile')),
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': 'Auftrag',
},
bases=('wagtailcore.page',),
),
]

View File

@ -1,20 +1,26 @@
from django.db import models
from django.db.models import DateTimeField, CharField
from django.db.models import Model, TextField
from wagtail import blocks
from wagtail.admin.panels import FieldPanel
from wagtail.blocks import StreamBlock
from wagtail.fields import StreamField
from wagtail.models import Page
from vbv_lernwelt.files.models import UploadFile
class AssignmentSubmission(Model):
created_at = models.DateTimeField(auto_now_add=True)
class ExplanationBlock(blocks.CharBlock):
class ExplanationBlock(blocks.StructBlock):
text = blocks.TextBlock()
class Meta:
icon = "comment"
class PerformanceObjectiveBlock(blocks.CharBlock):
class PerformanceObjectiveBlock(blocks.StructBlock):
text = blocks.TextBlock()
class Meta:
icon = "tick"
@ -24,8 +30,8 @@ class UserTextInputBlock(blocks.StaticBlock):
icon = "edit"
class UserConfirmationBlock(blocks.CharBlock):
confirmation_text = blocks.BooleanBlock()
class UserConfirmationBlock(blocks.StructBlock):
text = blocks.TextBlock()
class Meta:
icon = "tick-inverse"
@ -49,17 +55,15 @@ class TaskBlock(blocks.StructBlock):
class Assignment(Page):
# TODO: Referenz auf durchfhrung
starting_position = CharField(max_length=1024)
due = DateTimeField() # Zwingend teil der Durchführung
starting_position = TextField()
performance_objectives = StreamField(
[
("performance_objective", PerformanceObjectiveBlock()),
],
use_json_field=True,
)
effort_required = CharField(max_length=255)
assessment_tool = models.OneToOneField(UploadFile, on_delete=models.PROTECT)
effort_required = TextField()
assessment_document_url = TextField()
tasks = StreamField(
[
("task", TaskBlock()),
@ -69,16 +73,18 @@ class Assignment(Page):
content_panels = Page.content_panels + [
FieldPanel("starting_position"),
FieldPanel("due"),
FieldPanel("performance_objectives"),
FieldPanel("effort_required"),
FieldPanel("assessment_tool"),
FieldPanel("assessment_document_url"),
FieldPanel("tasks"),
]
subpage_types = []
class Meta:
verbose_name = "Auftrag"
class AssignmentPage(Page):
subpage_types = ["assignment.Assignment"]
parent_page_types = ["course.CoursePage"]

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,48 +1,60 @@
import wagtail_factories
from vbv_lernwelt.assignment.models import AssignmentPage, Assignment, TaskBlock
from vbv_lernwelt.assignment.models import (
ExplanationBlock,
UserConfirmationBlock,
PerformanceObjectiveBlock,
)
class ExplanationBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = "assignment.ExplanationBlock"
text = """Erläutere die Kundensituation und die Ausgangslage.
Hast du alle Informationen, die du für den Policen-Check benötigst?
Halte die wichtigsten Eckwerte des aktuellen Versicherungsverhältnisse in deiner Dokumentation fest (z.B wie lang wo versichert, Alter des Fahrzeugs, Kundenprofil, etc.)
"""
class UserTextInputBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = "assignment.UserTextInputBlock"
model = ExplanationBlock
class UserConfirmationBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = "assignment.UserConfirmationBlock"
text = "Ja, ich habe Motorfahrzeugversicherungspolice von jemandem aus meiner Familie oder meinem Freundeskreis erhalten."
confirmation_text = "Ja, ich habe Motorfahrzeugversicherungspolice von jemandem aus meiner Familie oder meinem Freundeskreis erhalten."
class Meta:
model = UserConfirmationBlock
class TaskBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = TaskBlock
title = "Teilauftrag"
file_submission_required = False
content = wagtail_factories.StreamFieldFactory(
[
("explanation", ExplanationBlockFactory()),
("user_text_input", UserTextInputBlockFactory()),
("user_text_input", "static_block"),
("user_confirmation", UserConfirmationBlockFactory()),
],
use_json_field=True,
)
class Meta:
model = TaskBlock
class PerformanceObjectiveBlockFactory(wagtail_factories.StructBlockFactory):
text = "Die Teilnehmer können die wichtigsten Eckwerte eines Versicherungsverhältnisses erfassen."
class Meta:
model = PerformanceObjectiveBlock
class AssignmentFactory(wagtail_factories.PageFactory):
title = "Auftrag"
starting_position = """Jemand aus deiner Familie oder aus deinem Freundeskreis möchte sein
Versicherungspolice überprüfen lassen. Diese Person kommt nun mit ihrer Police auf dich zu
und bittet dich als Versicherungsprofi, diese kritisch zu überprüfen und ihr gg. Anpassungsvorschläge
zu unterbreiten. In diesem Kompetenznachweis kannst du nun dein Wissen und Können im Bereich
der Motorfahrzeugversicherung unter Beweis stellen."""
class Meta:
model = Assignment

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.13 on 2023-03-29 13:39
from django.db import migrations
import wagtail.blocks
import wagtail.fields
class Migration(migrations.Migration):
dependencies = [
('learnpath', '0012_auto_20230309_0711'),
]
operations = [
migrations.AlterField(
model_name='learningcontent',
name='contents',
field=wagtail.fields.StreamField([('video', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('resource', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock()), ('text', wagtail.blocks.RichTextBlock(required=False))])), ('exercise', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('learningmodule', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('online_training', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('media_library', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('document', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('test', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('book', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('assignment', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.13 on 2023-03-29 13:44
from django.db import migrations
import wagtail.blocks
import wagtail.fields
class Migration(migrations.Migration):
dependencies = [
('learnpath', '0013_alter_learningcontent_contents'),
]
operations = [
migrations.AlterField(
model_name='learningcontent',
name='contents',
field=wagtail.fields.StreamField([('video', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('resource', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock()), ('text', wagtail.blocks.RichTextBlock(required=False))])), ('exercise', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('learningmodule', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('online_training', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('media_library', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('document', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('test', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('book', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('assignment', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.13 on 2023-03-30 13:30
from django.db import migrations
import wagtail.blocks
import wagtail.fields
class Migration(migrations.Migration):
dependencies = [
('learnpath', '0014_alter_learningcontent_contents'),
]
operations = [
migrations.AlterField(
model_name='learningcontent',
name='contents',
field=wagtail.fields.StreamField([('video', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('resource', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock()), ('text', wagtail.blocks.RichTextBlock(required=False))])), ('exercise', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('learningmodule', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('online_training', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('media_library', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('document', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('test', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('book', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('assignment', wagtail.blocks.StructBlock([('assignment_slug', wagtail.blocks.TextBlock())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None),
),
]

View File

@ -2,9 +2,11 @@ from wagtail import blocks
class AssignmentBlock(blocks.StructBlock):
description = blocks.TextBlock()
url = blocks.TextBlock()
text = blocks.RichTextBlock(required=False)
# TODO: Find way to let user select assignment through foreign key
# Wagtail block data is not stored as "true" database objects,
# but only as JSON text stored against the page, so there's no way to define relations such as ForeignKeys.
# A possible solution are InlinePanels: https://docs.wagtail.org/en/stable/reference/pages/panels.html#inlinepanel
assignment_slug = blocks.TextBlock()
class Meta:
icon = "media"