diff --git a/unisportomat/quiz/models.py b/unisportomat/quiz/models.py index 35cfa7d9fb1168289213e26aed44d1046a3c3667..fa320b1cf6b87dfdd15573c426992ec1aaf80c3b 100644 --- a/unisportomat/quiz/models.py +++ b/unisportomat/quiz/models.py @@ -1,5 +1,6 @@ """ Model definitions for the quiz """ - +import base64 +from django.core.files.uploadedfile import SimpleUploadedFile from django.core.exceptions import ValidationError from django.db import models @@ -161,6 +162,13 @@ class CallToMove(models.Model): def __str__(self): return self.text + def take_base64_image(self, image_data, image_type): + new_image = convert_base64_to_image(image_data, image_type, "activity_img") + + if new_image is None: + self.image.delete() + self.image = None + class KnowledgeSnack(models.Model): """Defines text and image that are used to show a KnowledgeSnack between questions""" @@ -171,6 +179,31 @@ class KnowledgeSnack(models.Model): def __str__(self): return self.text + def take_base64_image(self, image_data, image_type): + new_image = convert_base64_to_image(image_data, image_type, "snack_image") + + if new_image is None: + self.image.delete() + self.image = None + + +def convert_base64_to_image(image_data, image_type, image_name): + + if image_data == "": + return None + + ext = image_type.split("/")[-1] + + image_name += "." + ext + + image = SimpleUploadedFile( + content=base64.b64decode(image_data), + name=image_name, + content_type=image_type, + ) + + return image + class QuestionManager(models.Manager): """ diff --git a/unisportomat/quiz/serializers.py b/unisportomat/quiz/serializers.py index ed10610a5399767aa3ad74846ad18cfabbdca822..b9ead3bd0907c8183a58f6e67e2a7bbb3eeaba89 100644 --- a/unisportomat/quiz/serializers.py +++ b/unisportomat/quiz/serializers.py @@ -1,7 +1,11 @@ """ Serializers creating JSONs for every Model from .models """ + + +import base64 from rest_framework import serializers + from .models import Sport, Criterion, Question, validate_rating @@ -335,6 +339,7 @@ class SingleSnackTivitySerializer(serializers.BaseSerializer): if "image" in data.keys(): validated_data["image"] = data["image"] + validated_data["image_type"] = data["image_type"] return validated_data @@ -344,15 +349,20 @@ class SingleSnackTivitySerializer(serializers.BaseSerializer): has_image = object.image not in [None, ""] if has_image: - image_base64 = "Image Here!" + image_base64 = base64.b64encode(object.image.file.read()) + # TODO: Maybe rethink this? Dunno if unsafe. + image_type = "image/" + object.image.file.name.split(".")[-1] + else: image_base64 = "" + image_type = "" data = { "id": object.pk, "text_de": object.text_de, "text_en": object.text_en or "", "has_image": has_image, + "image_type": image_type, "image": image_base64, } diff --git a/unisportomat/quiz/views.py b/unisportomat/quiz/views.py index faf0e4650530df47cad928b02b82d5a3591a7382..52781718a382f1de4d4761b61ec913b0a0407732 100644 --- a/unisportomat/quiz/views.py +++ b/unisportomat/quiz/views.py @@ -3,7 +3,7 @@ Defines the views for the API """ # from django.shortcuts import render -from abc import abstractclassmethod, abstractproperty + from rest_framework import viewsets from rest_framework import filters from rest_framework.views import APIView @@ -26,7 +26,14 @@ from .serializers import ( SnackTivityListSerializer, SingleSnackTivitySerializer, ) -from .models import Sport, Criterion, Question, QuestionOrderEntry, KnowledgeSnack +from .models import ( + Sport, + Criterion, + Question, + QuestionOrderEntry, + KnowledgeSnack, + CallToMove, +) # Create your views here. @@ -540,8 +547,7 @@ class SnackTivityView(viewsets.ViewSet): new_object.text_en = data["text_en"] if "image" in data.keys(): - # TODO: Convert Base64 to Image Object - new_object.image = None + new_object.take_base64_image(data["image"], data["image_type"]) new_object.save() @@ -557,6 +563,62 @@ class SnackTivityView(viewsets.ViewSet): return Response(SingleSnackTivitySerializer(obj).data) + def update(self, request, pk=None): + """ + api/admin/<snacks||activities>/id PUT + Assumes every Data was given and fills them out for given PK + """ + + object = get_object_or_404(self.used_objects, pk=pk) + + data = SingleSnackTivitySerializer().to_internal_value(request.data) + + object.text_de = data["text_de"] + object.text_en = data["text_en"] + + object.take_base64_image(data["image"], data["image_type"]) + + object.save() + + return Response(SingleSnackTivitySerializer(object).data) + + def partial_update(self, request, pk=None): + """ + api/admin/<snacks||activities>/id PUT + Fills in Given Data in PK + """ + + object = get_object_or_404(self.used_objects, pk=pk) + + data = SingleSnackTivitySerializer().to_internal_value(request.data) + + if "text_de" in data.keys(): + object.text_de = data["text_de"] + if "text_en" in data.keys(): + object.text_en = data["text_en"] + + if "image" in data.keys(): + object.take_base64_image(data["image"], data["image_type"]) + + object.save() + + return Response(SingleSnackTivitySerializer(object).data) + + def destroy(self, request, pk=None): + """ + api/admin/<snacks||activities>/id DELETE + Deletes given PK + """ + + object = get_object_or_404(self.used_objects, pk=pk) + + # Delete Appended Image first + object.image.delete() + + object.delete() + + return Response(status=404) + class SnackListView(SnackTivityView): """ @@ -564,3 +626,11 @@ class SnackListView(SnackTivityView): """ used_objects = KnowledgeSnack + + +class ActivityView(SnackTivityView): + """ + View for ActivityLists and Activities, inheriting from SnackTivityView + """ + + used_objects = CallToMove diff --git a/unisportomat/unisportomat/urls.py b/unisportomat/unisportomat/urls.py index 61ddf1c78eb89b07a03393cfd8f6ad19826aca18..948c5b2286c36507bc2dc3c947fdaf1b6c5da5cb 100644 --- a/unisportomat/unisportomat/urls.py +++ b/unisportomat/unisportomat/urls.py @@ -25,6 +25,7 @@ router.register(r"question-list", views.QuestionListView, "question-list") router.register(r"small-sport-list", views.SmallSportListView, "small-sport-list") router.register(r"question", views.SmallQuestionListView, "small-question-list") router.register(r"snack", views.SnackListView, "snack") +router.register(r"activity", views.ActivityView, "activity") urlpatterns = [ path("admin/", admin.site.urls),