From 0d54437bf8d5979e44eac88af71fcc1e017c3921 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Wed, 8 Jun 2022 16:41:05 +0200 Subject: [PATCH] Add first api to complete learning contents --- server/vbv_lernwelt/completion/serializers.py | 9 +++++ .../vbv_lernwelt/completion/tests/test_api.py | 15 ++++++-- server/vbv_lernwelt/completion/views.py | 35 +++++++++++++++++-- server/vbv_lernwelt/core/utils.py | 16 +++++++++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 server/vbv_lernwelt/completion/serializers.py diff --git a/server/vbv_lernwelt/completion/serializers.py b/server/vbv_lernwelt/completion/serializers.py new file mode 100644 index 00000000..983a033c --- /dev/null +++ b/server/vbv_lernwelt/completion/serializers.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from vbv_lernwelt.completion.models import UserCircleCompletion + + +class UserCircleCompletionSerializer(serializers.ModelSerializer): + class Meta: + model = UserCircleCompletion + fields = ['id', 'created_at', 'updated_at', 'user', 'circle_key', 'json_data'] diff --git a/server/vbv_lernwelt/completion/tests/test_api.py b/server/vbv_lernwelt/completion/tests/test_api.py index 2e6c6a81..9ad24545 100644 --- a/server/vbv_lernwelt/completion/tests/test_api.py +++ b/server/vbv_lernwelt/completion/tests/test_api.py @@ -1,4 +1,6 @@ -from rest_framework.test import APITestCase, APIClient +import json + +from rest_framework.test import APITestCase from vbv_lernwelt.core.create_default_users import create_default_users from vbv_lernwelt.core.models import User @@ -20,9 +22,16 @@ class CompletionApiTestCase(APITestCase): self.client.login(username='student', password='student') def test_completeLearningContent_works(self): - learning_content_key = LearningContent.objects.get(title='Einleitung Circle "Anlayse"').translation_key + learning_content = LearningContent.objects.get(title='Einleitung Circle "Anlayse"') + learning_content_key = str(learning_content.translation_key) + circle_key = str(learning_content.get_parent().translation_key) + response = self.client.post(f'/api/completion/complete_learning_content/', { 'learning_content_key': learning_content_key }) - print(response.content) + response_json = response.json() + print(json.dumps(response.json())) + self.assertEqual(response.status_code, 201) + self.assertEqual(response_json['circle_key'], circle_key) + self.assertEqual(response_json['json_data']['completed_learning_contents'][learning_content_key]['learning_content_key'], learning_content_key) diff --git a/server/vbv_lernwelt/completion/views.py b/server/vbv_lernwelt/completion/views.py index fa03935f..b0312bcb 100644 --- a/server/vbv_lernwelt/completion/views.py +++ b/server/vbv_lernwelt/completion/views.py @@ -1,19 +1,48 @@ +from datetime import datetime + +import structlog from rest_framework.decorators import api_view from rest_framework.response import Response -from vbv_lernwelt.completion.models import LearningContentCompletion +from vbv_lernwelt.completion.models import LearningContentCompletion, UserCircleCompletion +from vbv_lernwelt.completion.serializers import UserCircleCompletionSerializer from vbv_lernwelt.learnpath.models import LearningContent +logger = structlog.get_logger(__name__) + @api_view(['POST']) def complete_learning_content(request): learning_content_key = request.data.get('learning_content_key') learning_content = LearningContent.objects.get(translation_key=learning_content_key) + circle_key = learning_content.get_parent().translation_key + LearningContentCompletion.objects.create( user=request.user, learning_content_key=learning_content_key, - circle_key=learning_content.get_parent().translation_key, + circle_key=circle_key, ) - return Response(status=201) + ucc, created = UserCircleCompletion.objects.get_or_create( + user=request.user, + circle_key=circle_key, + ) + + completed_learning_contents = ucc.json_data.get('completed_learning_contents', {}) + completed_learning_contents[learning_content_key] = { + 'learning_content_key': learning_content_key, + 'created_at': datetime.now().isoformat(), + } + ucc.json_data['completed_learning_contents'] = completed_learning_contents + ucc.save() + + logger.debug( + 'learning content completed', + label='completion_api', + circle_key=circle_key, + learning_content_key=learning_content_key, + user_id=request.user.id, + ) + + return Response(status=201, data=UserCircleCompletionSerializer(ucc).data) diff --git a/server/vbv_lernwelt/core/utils.py b/server/vbv_lernwelt/core/utils.py index 637707c7..d48f902c 100644 --- a/server/vbv_lernwelt/core/utils.py +++ b/server/vbv_lernwelt/core/utils.py @@ -4,6 +4,8 @@ import structlog from django.conf import settings from rest_framework.throttling import UserRateThrottle from structlog.types import EventDict + + #from .models import User def structlog_add_app_info( @@ -36,3 +38,17 @@ class HourUserRateThrottle(UserRateThrottle): class DayUserRateThrottle(UserRateThrottle): scope = "day-throttle" + + +def first_true(iterable, default=False, pred=None): + """Returns the first true value in the iterable. + + If no true value is found, returns *default* + + If *pred* is not None, returns the first item + for which pred(item) is true. + + """ + # first_true([a,b,c], x) --> a or b or c or x + # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x + return next(filter(pred, iterable), default)