From ef38d8be46b21f12ea0ebb34d5c5731e9cf56129 Mon Sep 17 00:00:00 2001 From: Aarni Halinen Date: Wed, 22 Jul 2020 19:11:27 +0300 Subject: [PATCH] Support uploading of images from event creation --- webapp/migrations/0067_basefeed_image.py | 18 ++++++++++++ webapp/models.py | 1 + webapp/serializers.py | 11 ++++---- webapp/utils.py | 35 ++++++++++++++++++++++++ webapp/views.py | 31 +++++++++++++++++---- 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 webapp/migrations/0067_basefeed_image.py diff --git a/webapp/migrations/0067_basefeed_image.py b/webapp/migrations/0067_basefeed_image.py new file mode 100644 index 0000000..3eb6eb3 --- /dev/null +++ b/webapp/migrations/0067_basefeed_image.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.5 on 2020-07-22 14:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('webapp', '0066_auto_20200622_2302'), + ] + + operations = [ + migrations.AddField( + model_name='basefeed', + name='image', + field=models.ImageField(blank=True, null=True, upload_to=''), + ), + ] diff --git a/webapp/models.py b/webapp/models.py index a7dc408..db2d3a2 100644 --- a/webapp/models.py +++ b/webapp/models.py @@ -42,6 +42,7 @@ class BaseFeed(models.Model): title = models.CharField(max_length=255) description = models.CharField(max_length=255) content = models.TextField() + image = models.ImageField(blank=True, null=True) class Feed(BaseFeed): diff --git a/webapp/serializers.py b/webapp/serializers.py index d034814..ab813a5 100644 --- a/webapp/serializers.py +++ b/webapp/serializers.py @@ -56,7 +56,8 @@ class EventSerializer(serializers.ModelSerializer): signup_id = serializers.PrimaryKeyRelatedField( many=True, source="signupForm", - queryset=SignupForm.objects.all() + queryset=SignupForm.objects.all(), + required=False ) tag_id = serializers.PrimaryKeyRelatedField( many=True, @@ -66,12 +67,12 @@ class EventSerializer(serializers.ModelSerializer): class Meta: model = Event - fields = ('id', 'tag_id', 'tags', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en', + fields = ('id', 'tag_id', 'tags', 'visible', 'image', 'title_fi', 'title_en', 'description_fi', 'description_en', 'content_fi', 'content_en', 'start_time', 'end_time', 'location', 'signup_id', 'signupForm') depth = 1 def create(self, validated_data): - signupForms = validated_data.pop('signupForm') + signupForms = validated_data.pop('signupForm', []) tags = validated_data.pop('tags') event = Event.objects.create(**validated_data) for form in signupForms: @@ -82,7 +83,7 @@ class EventSerializer(serializers.ModelSerializer): return event def update(self, instance, validated_data): - signupForms = validated_data.pop('signupForm') + signupForms = validated_data.pop('signupForm', []) instance = super(EventSerializer, self).update(instance, validated_data) instance.signupForm.clear() for form_data in signupForms: @@ -114,7 +115,7 @@ class FeedSerializer(serializers.ModelSerializer): class Meta: model = Feed - fields = ('id', 'tags', 'tag_id', 'visible', 'title_fi', 'title_en', 'description_fi', 'description_en', + fields = ('id', 'tags', 'tag_id', 'visible', 'image', 'title_fi', 'title_en', 'description_fi', 'description_en', 'content_fi', 'content_en', 'publish_time', 'autohide', 'autohide_enabled') depth = 1 diff --git a/webapp/utils.py b/webapp/utils.py index d3d00a1..299cd52 100644 --- a/webapp/utils.py +++ b/webapp/utils.py @@ -9,7 +9,42 @@ from datetime import timedelta import logging from django.conf import settings from django.template.loader import render_to_string +from django.core.files.base import ContentFile +import base64 +import uuid from sikweb.settings import FRONTEND_URL, URL, EMAIL_API_KEY, EMAIL_API_SECRET, DEFAULT_EMAIL_FROM, DEFAULT_EMAIL_FROM_ADDR, ENABLE_AUTOMATIC_EMAILS +import imghdr + + +def get_file_extension(file_name, decoded_file): + extension = imghdr.what(file_name, decoded_file) + extension = "jpg" if extension == "jpeg" else extension + return extension + + +def decode_base64_file(data): + # Check if this is a base64 string + if isinstance(data, str): + # Check if the base64 string is in the "data:" format + if 'data:' in data and ';base64,' in data: + # Break out the header from the base64 content + header, data = data.split(';base64,') + + # Try to decode the file. Return validation error if it fails. + try: + decoded_file = base64.b64decode(data) + except TypeError: + TypeError('invalid_image') + + # Generate file name: + file_name = str(uuid.uuid4()) + + # Get the file name extension: + file_extension = get_file_extension(file_name, decoded_file) + + complete_file_name = "%s.%s" % (file_name, file_extension, ) + + return ContentFile(decoded_file, name=complete_file_name) def month_from_now(): diff --git a/webapp/views.py b/webapp/views.py index 32159db..ffaf74b 100644 --- a/webapp/views.py +++ b/webapp/views.py @@ -21,6 +21,7 @@ from webapp.models import Event, SignupForm, Signup, TemplateQuestion, Feed, Com from webapp.serializers import (EventSerializer, SignupFormSerializer, SignupSerializer, SavedQuestionsSerializer, FeedSerializer, CommitteeSerializer, OccupationSerializer, TagSerializer) +from webapp.utils import decode_base64_file class SignupPermission(BasePermission): @@ -41,9 +42,9 @@ class EventViewSet(viewsets.ModelViewSet): ordering = ["start_time"] serializer_class = EventSerializer permission_classes = [IsAuthenticatedOrReadOnly] - filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) - filter_fields = '__all__' - search_fields = '__all__' + # filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) + # filter_fields = '__all__' + # search_fields = '__all__' def get_queryset(self): if self.request.user.is_authenticated: @@ -54,6 +55,24 @@ class EventViewSet(viewsets.ModelViewSet): return Event.objects.filter(visible=True, end_time__gt=since).order_by('start_time') return Event.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time') + def create(self, request, *args, **kwargs): + raw_image = request.data.get("image", None) + if raw_image is not None: + image = decode_base64_file(raw_image) + request.data.update({ + "image": image + }) + return super().create(request, *args, **kwargs) + + def update(self, request, *args, **kwargs): + raw_image = request.data.get("image", None) + if raw_image is not None: + image = decode_base64_file(raw_image) + request.data.update({ + "image": image + }) + return super().update(request, *args, **kwargs) + class SignupFormViewSet(viewsets.ModelViewSet): queryset = SignupForm.objects.all() @@ -138,9 +157,9 @@ class FeedViewSet(viewsets.ModelViewSet): queryset = Feed.objects.all() serializer_class = FeedSerializer permission_classes = [IsAuthenticatedOrReadOnly] - filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) - filter_fields = '__all__' - search_fields = '__all__' + # filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter) + # filter_fields = '__all__' + # search_fields = '__all__' def get_queryset(self): if self.request.user.is_authenticated: