Add CourseSession serializer and view
This commit is contained in:
parent
05e02449c8
commit
17eaf80d2c
|
|
@ -21,6 +21,7 @@ from vbv_lernwelt.core.views import (
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.views import (
|
from vbv_lernwelt.course.views import (
|
||||||
course_page_api_view,
|
course_page_api_view,
|
||||||
|
get_course_sessions,
|
||||||
mark_course_completion,
|
mark_course_completion,
|
||||||
request_course_completion,
|
request_course_completion,
|
||||||
)
|
)
|
||||||
|
|
@ -59,6 +60,7 @@ urlpatterns = [
|
||||||
name="generate_web_component_icons"),
|
name="generate_web_component_icons"),
|
||||||
|
|
||||||
# course
|
# course
|
||||||
|
path(r"api/course/sessions/", get_course_sessions, name="get_course_sessions"),
|
||||||
path(r"api/course/page/<slug:slug>/", course_page_api_view,
|
path(r"api/course/page/<slug:slug>/", course_page_api_view,
|
||||||
name="course_page_api_view"),
|
name="course_page_api_view"),
|
||||||
path(r"api/course/completion/mark/", mark_course_completion,
|
path(r"api/course/completion/mark/", mark_course_completion,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,15 @@ import djclick as click
|
||||||
from vbv_lernwelt.competence.create_default_competence_profile import (
|
from vbv_lernwelt.competence.create_default_competence_profile import (
|
||||||
create_default_competence_profile,
|
create_default_competence_profile,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.course.consts import (
|
||||||
|
COURSE_TEST_ID,
|
||||||
|
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
|
)
|
||||||
from vbv_lernwelt.course.creators.test_course import create_test_course
|
from vbv_lernwelt.course.creators.test_course import create_test_course
|
||||||
from vbv_lernwelt.course.creators.versicherungsvermittlerin import (
|
from vbv_lernwelt.course.creators.versicherungsvermittlerin import (
|
||||||
create_versicherungsvermittlerin_with_categories,
|
create_versicherungsvermittlerin_with_categories,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.course.models import CourseSession
|
||||||
from vbv_lernwelt.learnpath.create_default_learning_path import (
|
from vbv_lernwelt.learnpath.create_default_learning_path import (
|
||||||
create_default_learning_path,
|
create_default_learning_path,
|
||||||
)
|
)
|
||||||
|
|
@ -24,7 +29,6 @@ def command():
|
||||||
create_versicherungsvermittlerin_with_categories()
|
create_versicherungsvermittlerin_with_categories()
|
||||||
|
|
||||||
create_default_learning_path()
|
create_default_learning_path()
|
||||||
|
|
||||||
create_default_competence_profile()
|
create_default_competence_profile()
|
||||||
|
|
||||||
# media library
|
# media library
|
||||||
|
|
@ -34,3 +38,13 @@ def command():
|
||||||
|
|
||||||
# test course
|
# test course
|
||||||
create_test_course()
|
create_test_course()
|
||||||
|
|
||||||
|
# course sessions
|
||||||
|
CourseSession.objects.create(
|
||||||
|
course_id=COURSE_TEST_ID,
|
||||||
|
title="Test Lehrgang Session",
|
||||||
|
)
|
||||||
|
CourseSession.objects.create(
|
||||||
|
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||||
|
title="Versicherungsvermittler/in Session",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 3.2.13 on 2022-11-07 13:30
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("course", "0002_auto_20221014_0933"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="coursepage",
|
||||||
|
name="course",
|
||||||
|
field=models.OneToOneField(
|
||||||
|
on_delete=django.db.models.deletion.PROTECT, to="course.course"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -18,6 +18,30 @@ class Course(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Lehrgang")
|
verbose_name = _("Lehrgang")
|
||||||
|
|
||||||
|
def get_learning_path_url(self):
|
||||||
|
from vbv_lernwelt.learnpath.models import LearningPath
|
||||||
|
|
||||||
|
learning_path_page = (
|
||||||
|
self.coursepage.get_children().exact_type(LearningPath).first()
|
||||||
|
)
|
||||||
|
return learning_path_page.specific.get_frontend_url()
|
||||||
|
|
||||||
|
def get_competence_url(self):
|
||||||
|
from vbv_lernwelt.competence.models import CompetenceProfilePage
|
||||||
|
|
||||||
|
competence_page = (
|
||||||
|
self.coursepage.get_children().exact_type(CompetenceProfilePage).first()
|
||||||
|
)
|
||||||
|
return competence_page.specific.get_frontend_url()
|
||||||
|
|
||||||
|
def get_media_library_url(self):
|
||||||
|
from vbv_lernwelt.media_library.models import MediaLibraryPage
|
||||||
|
|
||||||
|
media_library_page = (
|
||||||
|
self.coursepage.get_children().exact_type(MediaLibraryPage).first()
|
||||||
|
)
|
||||||
|
return media_library_page.specific.get_frontend_url()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title}"
|
return f"{self.title}"
|
||||||
|
|
||||||
|
|
@ -86,8 +110,12 @@ class CourseBasePage(Page):
|
||||||
|
|
||||||
class CoursePage(CourseBasePage):
|
class CoursePage(CourseBasePage):
|
||||||
content_panels = Page.content_panels
|
content_panels = Page.content_panels
|
||||||
subpage_types = ["learnpath.LearningPath", "media_library.MediaLibraryPage"]
|
subpage_types = [
|
||||||
course = models.ForeignKey("course.Course", on_delete=models.PROTECT)
|
"learnpath.LearningPath",
|
||||||
|
"competence.CompetenceProfilePage",
|
||||||
|
"media_library.MediaLibraryPage",
|
||||||
|
]
|
||||||
|
course = models.OneToOneField("course.Course", on_delete=models.PROTECT)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Lehrgang-Seite")
|
verbose_name = _("Lehrgang-Seite")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from vbv_lernwelt.course.models import CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||||
|
|
||||||
|
|
||||||
def has_course_access_by_page_request(request, obj):
|
def has_course_access_by_page_request(request, obj):
|
||||||
|
|
@ -21,3 +21,14 @@ def has_course_access(user, course):
|
||||||
|
|
||||||
# TODO check school class access
|
# TODO check school class access
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def course_sessions_for_user_qs(user):
|
||||||
|
if user.is_superuser:
|
||||||
|
return CourseSession.objects.all()
|
||||||
|
|
||||||
|
course_sessions = CourseSession.objects.filter(
|
||||||
|
course_session_user__user=user
|
||||||
|
).distinct()
|
||||||
|
|
||||||
|
return course_sessions
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import Course, CourseCategory, CourseCompletion
|
from vbv_lernwelt.course.models import (
|
||||||
|
Course,
|
||||||
|
CourseCategory,
|
||||||
|
CourseCompletion,
|
||||||
|
CourseSession,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CourseSerializer(serializers.ModelSerializer):
|
class CourseSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -34,3 +39,38 @@ class CourseCompletionSerializer(serializers.ModelSerializer):
|
||||||
"completion_status",
|
"completion_status",
|
||||||
"additional_json_data",
|
"additional_json_data",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CourseSessionSerializer(serializers.ModelSerializer):
|
||||||
|
learning_path_url = serializers.SerializerMethodField()
|
||||||
|
competence_url = serializers.SerializerMethodField()
|
||||||
|
media_library_url = serializers.SerializerMethodField()
|
||||||
|
course = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_course(self, obj):
|
||||||
|
return CourseSerializer(obj.course).data
|
||||||
|
|
||||||
|
def get_learning_path_url(self, obj):
|
||||||
|
return obj.course.get_learning_path_url()
|
||||||
|
|
||||||
|
def get_media_library_url(self, obj):
|
||||||
|
return obj.course.get_media_library_url()
|
||||||
|
|
||||||
|
def get_competence_url(self, obj):
|
||||||
|
return obj.course.get_competence_url()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CourseSession
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"course",
|
||||||
|
"title",
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
"additional_json_data",
|
||||||
|
"learning_path_url",
|
||||||
|
"competence_url",
|
||||||
|
"media_library_url",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,13 @@ from wagtail.models import Page
|
||||||
from vbv_lernwelt.core.utils import api_page_cache_get_or_set
|
from vbv_lernwelt.core.utils import api_page_cache_get_or_set
|
||||||
from vbv_lernwelt.course.models import CourseCompletion
|
from vbv_lernwelt.course.models import CourseCompletion
|
||||||
from vbv_lernwelt.course.permissions import (
|
from vbv_lernwelt.course.permissions import (
|
||||||
|
course_sessions_for_user_qs,
|
||||||
has_course_access_by_page_request,
|
has_course_access_by_page_request,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.serializers import CourseCompletionSerializer
|
from vbv_lernwelt.course.serializers import (
|
||||||
|
CourseCompletionSerializer,
|
||||||
|
CourseSessionSerializer,
|
||||||
|
)
|
||||||
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
@ -97,3 +101,17 @@ def mark_course_completion(request):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
return Response({"error": str(e)}, status=404)
|
return Response({"error": str(e)}, status=404)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(["GET"])
|
||||||
|
def get_course_sessions(request):
|
||||||
|
try:
|
||||||
|
course_sessions = course_sessions_for_user_qs(request.user)
|
||||||
|
return Response(
|
||||||
|
status=200, data=CourseSessionSerializer(course_sessions, many=True).data
|
||||||
|
)
|
||||||
|
except PermissionDenied as e:
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
return Response({"error": str(e)}, status=404)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
# Generated by Django 3.2.13 on 2022-11-07 13:30
|
||||||
|
|
||||||
|
import wagtail.blocks
|
||||||
|
import wagtail.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("learnpath", "0007_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()),
|
||||||
|
("url", wagtail.blocks.TextBlock()),
|
||||||
|
("text", wagtail.blocks.RichTextBlock(required=False)),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"placeholder",
|
||||||
|
wagtail.blocks.StructBlock(
|
||||||
|
[
|
||||||
|
("description", wagtail.blocks.TextBlock()),
|
||||||
|
("url", wagtail.blocks.TextBlock()),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
use_json_field=None,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue