From 53bfa878ba5c1841afe2a35c89a8f9f13c5a5a4e Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Thu, 6 Feb 2020 22:47:57 +0300 Subject: [PATCH] establishment gallery --- apps/gallery/models.py | 23 ++++++++++++++++++- apps/gallery/serializers.py | 45 +++++++++++++++++++++++++++++++++++++ apps/gallery/urls.py | 2 ++ apps/gallery/views.py | 14 +++++++++++- 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/apps/gallery/models.py b/apps/gallery/models.py index 88a50035..dcd38faa 100644 --- a/apps/gallery/models.py +++ b/apps/gallery/models.py @@ -16,6 +16,12 @@ class Image(BaseAttributes, SORLImageMixin, PlatformMixin): HORIZONTAL = 0 VERTICAL = 1 + MEDIA_TYPES = ( + _('photo'), + _('video'), + _('youtube'), + ) + ORIENTATIONS = ( (HORIZONTAL, _('Horizontal')), (VERTICAL, _('Vertical')), @@ -27,7 +33,7 @@ class Image(BaseAttributes, SORLImageMixin, PlatformMixin): blank=True, null=True, default=None, verbose_name=_('image orientation')) title = models.CharField(_('title'), max_length=255, default='') - is_public = models.BooleanField(default=False, verbose_name=_('Is media source public')) + is_public = models.BooleanField(default=True, verbose_name=_('Is media source public')) preview = SORLImageField(max_length=255, upload_to=image_path, verbose_name=_('image preview'), null=True, default=None) @@ -45,6 +51,21 @@ class Image(BaseAttributes, SORLImageMixin, PlatformMixin): """String representation""" return f'{self.id}' + @property + def type(self) -> str: + if self.image: + return self.MEDIA_TYPES[0] + if self.link is not None and self.link.endswith('.mp4'): + return self.MEDIA_TYPES[1] + return self.MEDIA_TYPES[2] + + @property + def image_size_in_KB(self): + try: + return self.image.size / 1024 if self.image else None + except FileNotFoundError: + return None + def delete_image(self, completely: bool = True): """ Deletes an instance and crops of instance from media storage. diff --git a/apps/gallery/serializers.py b/apps/gallery/serializers.py index f7d2d2a3..5d270abf 100644 --- a/apps/gallery/serializers.py +++ b/apps/gallery/serializers.py @@ -5,6 +5,9 @@ from sorl.thumbnail import get_thumbnail from sorl.thumbnail.parsers import parse_crop, ThumbnailParseError from django.utils.translation import gettext_lazy as _ from django.conf import settings +from django.shortcuts import get_object_or_404 +from establishment.models import Establishment +from account.serializers.common import UserBaseSerializer from . import models @@ -45,6 +48,48 @@ class ImageSerializer(serializers.ModelSerializer): return attrs +class EstablishmentGallerySerializer(serializers.ModelSerializer): + """Serializer for creating and retrieving establishment media""" + type = serializers.CharField(read_only=True) + created_by = UserBaseSerializer(read_only=True, allow_null=True) + image_size_in_KB = serializers.DecimalField(read_only=True, decimal_places=2, max_digits=20) + + class Meta: + model = models.Image + fields = ( + 'id', + 'image', + 'type', + 'link', + 'order', + 'preview', + 'is_public', + 'title', + 'created_by', + 'image_size_in_KB', + ) + extra_kwargs = { + 'created': {'read_only': True}, + } + + def validate(self, attrs): + """Overridden validate method.""" + image = attrs.get('image') + + if image and image.size >= settings.FILE_UPLOAD_MAX_MEMORY_SIZE: + raise serializers.ValidationError({'detail': _('File size too large: %s bytes') % image.size}) + + return attrs + + def create(self, validated_data): + establishment = get_object_or_404(klass=Establishment, pk=self.context['view'].kwargs['establishment_id']) + instance = super().create(validated_data) + instance.created_by = self.context['request'].user + instance.establishment_set.add(establishment) + instance.save() + return instance + + class CropImageSerializer(ImageSerializer): """Serializers for image crops.""" diff --git a/apps/gallery/urls.py b/apps/gallery/urls.py index 987685cb..834dc347 100644 --- a/apps/gallery/urls.py +++ b/apps/gallery/urls.py @@ -7,6 +7,8 @@ app_name = 'gallery' urlpatterns = [ path('', views.ImageListCreateView.as_view(), name='list-create'), + path('for_establishment//', views.MediaForEstablishmentView.as_view(), + name='establishment-media'), path('/', views.ImageRetrieveDestroyView.as_view(), name='retrieve-destroy'), path('/crop/', views.CropImageCreateView.as_view(), name='create-crop'), ] diff --git a/apps/gallery/views.py b/apps/gallery/views.py index 3b5063ba..dfb76019 100644 --- a/apps/gallery/views.py +++ b/apps/gallery/views.py @@ -4,7 +4,8 @@ from rest_framework import generics, status from rest_framework.response import Response from utils.methods import get_permission_classes -from utils.permissions import IsContentPageManager +from utils.permissions import IsContentPageManager, IsCountryAdmin, IsEstablishmentManager, \ + IsProducerFoodInspector, IsEstablishmentAdministrator from . import tasks, models, serializers @@ -22,6 +23,17 @@ class ImageListCreateView(ImageBaseView, generics.ListCreateAPIView): """List/Create Image view.""" +class MediaForEstablishmentView(ImageBaseView, generics.ListCreateAPIView): + """View for creating and retrieving certain establishment media.""" + pagination_class = None + permission_classes = (IsCountryAdmin, IsEstablishmentAdministrator, IsEstablishmentManager, IsProducerFoodInspector) + serializer_class = serializers.EstablishmentGallerySerializer + + def get_queryset(self): + return super().get_queryset().filter(establishment__pk=self.kwargs['establishment_id'])\ + .order_by('-order').prefetch_related('created_by') + + class ImageRetrieveDestroyView(ImageBaseView, generics.RetrieveDestroyAPIView): """Destroy view for model Image"""