diff --git a/api/v1/__init__.py b/api/v1/__init__.py index 423698bd..8c95c2f2 100644 --- a/api/v1/__init__.py +++ b/api/v1/__init__.py @@ -1,4 +1,11 @@ -from rest_framework import viewsets +import imghdr +import base64 +import six +import uuid + +from django.core.files.base import ContentFile + +from rest_framework import serializers, viewsets from rest_framework.response import Response # https://gist.github.com/ivlevdenis/a0c8f5b472b6b8550bbb016c6a30e0be @@ -41,3 +48,27 @@ class ExtendViewSet(object): class ExtendedModelViewSet(ExtendViewSet, viewsets.ModelViewSet): pass + + +class Base64ImageField(serializers.ImageField): + + def to_internal_value(self, data): + if isinstance(data, six.string_types): + if 'data:' in data and ';base64,' in data: + header, data = data.split(';base64,') + try: + decoded_file = base64.b64decode(data) + except TypeError: + self.fail('invalid_image') + + file_name = str(uuid.uuid4())[:12] + file_extension = self.get_file_extension( + file_name, decoded_file) + complete_file_name = "%s.%s" % (file_name, file_extension,) + data = ContentFile(decoded_file, name=complete_file_name) + return super().to_internal_value(data) + + def get_file_extension(self, file_name, decoded_file): + extension = imghdr.what(file_name, decoded_file) + extension = "jpg" if extension == "jpeg" else extension + return extension diff --git a/api/v1/serializers.py b/api/v1/serializers.py index 2b1bf61a..9bf48ad6 100644 --- a/api/v1/serializers.py +++ b/api/v1/serializers.py @@ -1,6 +1,8 @@ from django.contrib.auth import get_user_model from rest_framework import serializers +from . import Base64ImageField + from apps.course.models import Category, Course, Material, Lesson, Like from apps.content.models import ( Image, Text, ImageText, Video, @@ -89,6 +91,7 @@ class CourseSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'cover', 'created_at', 'update_at', ) @@ -110,6 +113,7 @@ class LessonSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'cover', 'created_at', 'update_at', ) @@ -131,6 +135,7 @@ class ImageSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'img', 'created_at', 'update_at', ) @@ -173,6 +178,7 @@ class ImageTextSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'img', 'created_at', 'update_at', ) @@ -232,6 +238,7 @@ class GalleryImageSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'image', 'created_at', 'update_at', ) @@ -269,8 +276,15 @@ class UserSerializer(serializers.ModelSerializer): read_only_fields = ( 'id', + 'photo', 'date_joined', 'is_staff', 'fb_id', 'fb_data', ) + + +class UserPhotoSerializer(serializers.Serializer): + photo = Base64ImageField( + required=False, allow_empty_file=True, allow_null=True + ) diff --git a/api/v1/views.py b/api/v1/views.py index ddebe250..5dd298bc 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -1,6 +1,8 @@ from django.contrib.auth import get_user_model from rest_framework import viewsets +from rest_framework.decorators import detail_route, list_route +from rest_framework.response import Response from . import ExtendedModelViewSet from .serializers import ( @@ -9,7 +11,8 @@ from .serializers import ( ImageSerializer, TextSerializer, ImageTextSerializer, VideoSerializer, GallerySerializer, GalleryImageSerializer, - UserSerializer, LessonSerializer, + UserSerializer, UserPhotoSerializer, + LessonSerializer, ) from .permissions import IsAdmin, IsAdminOrIsSelf, IsAuthorOrAdmin, IsAuthorObjectOrAdmin @@ -152,13 +155,29 @@ class GalleryImageViewSet(ExtendedModelViewSet): class UserViewSet(ExtendedModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer + serializer_class_map = { + 'upload_photo': UserPhotoSerializer, + } filter_fields = ('is_staff', 'is_active', 'role', 'gender', 'is_email_proved', 'fb_id',) search_fields = ('email', 'first_name', 'last_name', 'country', 'city', 'fb_id',) ordering_fields = ('email', 'first_name', 'last_name', 'country', 'city', 'date_joined',) + # permission_classes = (IsAdminOrIsSelf,) # permission_map = { # 'delete': IsAdmin, # } + + @detail_route(methods=['post'], url_path='upload-photo') + def upload_photo(self, request, pk=None): + user = self.get_object() + serializer = self.get_serializer() + serialized_data = serializer(data=request.data) + if serialized_data.is_valid(): + user.photo = serialized_data['photo'] + user.save() + return Response({'success': True}) + else: + return Response({'success': False})