From 4269bfde8eaf67af235e975d5c39cef804db13d8 Mon Sep 17 00:00:00 2001 From: phzhik Date: Fri, 7 Jul 2023 06:05:14 +0400 Subject: [PATCH] * Upload base64 images & generate preview --- store/models.py | 37 ++++++++++++++++++++++--------------- store/serializers.py | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/store/models.py b/store/models.py index 8c10803..55991cf 100644 --- a/store/models.py +++ b/store/models.py @@ -362,6 +362,7 @@ class Checklist(models.Model): def preview_image(self): # Prefer annotated field if hasattr(self, '_images'): + # Get first is_preview image from all images return next(filter(lambda x: x.is_preview, self._images), None) return self.images.filter(is_preview=True).first() @@ -371,7 +372,7 @@ class Checklist(models.Model): return getattr(self.preview_image, 'image', None) @property - def main_images(self): + def main_images(self) -> list: # Prefer prefetched field if hasattr(self, '_images'): return [img for img in self._images if not img.is_preview] @@ -385,6 +386,24 @@ class Checklist(models.Model): def __str__(self): return f'{self.id}' + def generate_preview(self, source_img: Image = None): + source_img = source_img or next(iter(self.main_images), None) + if not source_img: + return + + # Render preview image + preview = create_preview(source_img.image.path, size=self.size, price_rub=self.price_rub, title=self.title) + + # Prepare bytes + image_io = BytesIO() + preview.save(image_io, format='JPEG') + + # Create Image model and save it + image_obj = Image(is_preview=True, checklist_id=self.id) + image_obj.image.save(name=f'{self.id}_preview.jpg', + content=ContentFile(image_io.getvalue()), + save=True) + def save(self, *args, **kwargs): if self.id: old_obj = Checklist.objects.filter(id=self.id).first() @@ -400,20 +419,8 @@ class Checklist(models.Model): self.cdek_barcode_pdf.save(f'{self.id}_barcode.pdf', pdf_file) # Create preview image - if self.images.exists() and not self.preview_image: - # Render preview image - original = self.images.first().image - preview = create_preview(original.path, size=self.size, price_rub=self.price_rub, title=self.title) - - # Prepare bytes - image_io = BytesIO() - preview.save(image_io, format='JPEG') - - # Create Image model and save it - image_obj = Image(is_preview=True, checklist_id=self.id) - image_obj.image.save(name=f'{self.id}_preview.jpg', - content=ContentFile(image_io.getvalue()), - save=True) + if not self.preview_image: + self.generate_preview() super().save(*args, **kwargs) diff --git a/store/serializers.py b/store/serializers.py index 35076c3..d3b7d94 100644 --- a/store/serializers.py +++ b/store/serializers.py @@ -54,9 +54,13 @@ class ImageSerializer(serializers.ModelSerializer): fields = ('image',) -class ChecklistImageListSerializer(serializers.ListSerializer): +class ImageListSerializer(serializers.ListSerializer): child = ImageSerializer() + def to_internal_value(self, data): + data = [{"image": x} for x in data] + return super().to_internal_value(data) + def to_representation(self, data): images = super().to_representation(data) return [image['image'] for image in images] @@ -64,11 +68,11 @@ class ChecklistImageListSerializer(serializers.ListSerializer): class ChecklistSerializer(serializers.ModelSerializer): id = serializers.CharField(read_only=True) - managerid = serializers.PrimaryKeyRelatedField(source='manager.id', read_only=True, allow_null=True) + managerid = serializers.PrimaryKeyRelatedField(source='manager_id', read_only=True, allow_null=True) link = serializers.URLField(source='product_link', required=False) category = serializers.SlugRelatedField(slug_field='slug', queryset=Category.objects.all()) - # image = Base64ImageField(source='images', many=True, queryset=Image.objects.all()) + image = ImageListSerializer(source='main_images') previewimage = serializers.ImageField(source='preview_image_url', read_only=True) promo = serializers.SlugRelatedField(source='promocode', slug_field='name', @@ -105,6 +109,28 @@ class ChecklistSerializer(serializers.ModelSerializer): startDate = serializers.DateTimeField(source='created_at', read_only=True) currentDate = serializers.DateTimeField(source='status_updated_at', read_only=True) + def _create_images(self, instance, images): + img_objs = [Image(image=img['image'], checklist_id=instance.id) for img in images] + img_objs = Image.objects.bulk_create(img_objs) + + instance.generate_preview(next(iter(img_objs), None)) + + def create(self, validated_data): + images = validated_data.pop('main_images', []) + instance = super().create(validated_data) + self._create_images(instance, images) + return instance + + def update(self, instance, validated_data): + images = validated_data.pop('main_images', []) + instance: Checklist = super().update(instance, validated_data) + + # Replace images basically + instance.images.all().delete() + self._create_images(instance, images) + instance.refresh_from_db(fields=('images',)) + return instance + @staticmethod def get_yuan_rate(obj: Checklist): return GlobalSettings.load().yuan_rate @@ -126,7 +152,7 @@ class ChecklistSerializer(serializers.ModelSerializer): fields = ('id', 'status', 'managerid', 'link', 'category', 'subcategory', 'brand', 'model', 'size', - # 'image', + 'image', 'previewimage', 'currency', 'curencycurency2', 'currency3', 'chinadelivery', 'chinadelivery2', 'comission', 'promo',