diff --git a/apps/establishment/management/commands/fill_artisan_default_image.py b/apps/establishment/management/commands/fill_artisan_default_image.py new file mode 100644 index 00000000..1231ba76 --- /dev/null +++ b/apps/establishment/management/commands/fill_artisan_default_image.py @@ -0,0 +1,68 @@ +import boto3 +from django.conf import settings +from django.core.management.base import BaseCommand + +from establishment.models import EstablishmentSubType +from gallery.models import Image + + +class Command(BaseCommand): + help = """ + Fill establishment type by index names. + Steps: + 1 Upload default images into s3 bucket + 2 Run command ./manage.py fill_artisan_default_image + """ + + def add_arguments(self, parser): + parser.add_argument( + '--template_image_folder_name', + help='Template image folder in Amazon S3 bucket' + ) + + def handle(self, *args, **kwargs): + not_updated = 0 + template_image_folder_name = kwargs.get('template_image_folder_name') + if (template_image_folder_name and + hasattr(settings, 'AWS_ACCESS_KEY_ID') and + hasattr(settings, 'AWS_SECRET_ACCESS_KEY') and + hasattr(settings, 'AWS_STORAGE_BUCKET_NAME')): + to_update = [] + s3 = boto3.resource('s3') + s3_bucket = s3.Bucket(settings.AWS_STORAGE_BUCKET_NAME) + + for object_summary in s3_bucket.objects.filter(Prefix=f'media/{template_image_folder_name}/'): + uri_path = object_summary.key + filename = uri_path.split('/')[-1:][0] + if filename: + artisan_index_slice = filename.split('.')[:-1][0] \ + .split('_')[2:] + if len(artisan_index_slice) > 1: + artisan_index_name = '_'.join(artisan_index_slice) + else: + artisan_index_name = artisan_index_slice[0] + + attachment_suffix_url = f'{template_image_folder_name}/{filename}' + + # check artisan in db + artisan_qs = EstablishmentSubType.objects.filter(index_name__iexact=artisan_index_name, + establishment_type__index_name__iexact='artisan') + if artisan_qs.exists(): + artisan = artisan_qs.first() + image, created = Image.objects.get_or_create(image=attachment_suffix_url, + defaults={ + 'image': attachment_suffix_url, + 'orientation': Image.HORIZONTAL, + 'title': f'{artisan.__str__()} ' + f'{artisan.id} - ' + f'{attachment_suffix_url}'}) + if created: + # update artisan instance + artisan.default_image = image + to_update.append(artisan) + else: + not_updated += 1 + + EstablishmentSubType.objects.bulk_update(to_update, ['default_image', ]) + self.stdout.write(self.style.WARNING(f'Updated {len(to_update)} objects.')) + self.stdout.write(self.style.WARNING(f'Not updated {not_updated} objects.')) \ No newline at end of file diff --git a/apps/establishment/migrations/0069_auto_20191220_1007.py b/apps/establishment/migrations/0069_auto_20191220_1007.py new file mode 100644 index 00000000..6225c592 --- /dev/null +++ b/apps/establishment/migrations/0069_auto_20191220_1007.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.7 on 2019-12-20 10:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('gallery', '0007_auto_20191211_1528'), + ('establishment', '0068_auto_20191220_0914'), + ] + + operations = [ + migrations.AddField( + model_name='establishmentsubtype', + name='default_image', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='establishment_sub_types', to='gallery.Image', verbose_name='default image'), + ), + migrations.AddField( + model_name='establishmenttype', + name='default_image', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='establishment_types', to='gallery.Image', verbose_name='default image'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 2442d449..b4655b24 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -51,6 +51,10 @@ class EstablishmentType(TranslatedFieldsMixin, ProjectBaseMixin): tag_categories = models.ManyToManyField('tag.TagCategory', related_name='establishment_types', verbose_name=_('Tag')) + default_image = models.ForeignKey('gallery.Image', on_delete=models.SET_NULL, + related_name='establishment_types', + blank=True, null=True, default=None, + verbose_name='default image') class Meta: """Meta class.""" @@ -85,6 +89,10 @@ class EstablishmentSubType(ProjectBaseMixin, TranslatedFieldsMixin): tag_categories = models.ManyToManyField('tag.TagCategory', related_name='establishment_subtypes', verbose_name=_('Tag')) + default_image = models.ForeignKey('gallery.Image', on_delete=models.SET_NULL, + related_name='establishment_sub_types', + blank=True, null=True, default=None, + verbose_name='default image') objects = EstablishmentSubTypeManager() diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 19b4b764..1e7a153a 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -97,6 +97,8 @@ class MenuRUDSerializers(ProjectModelSerializer): class EstablishmentTypeBaseSerializer(serializers.ModelSerializer): """Serializer for EstablishmentType model.""" name_translated = TranslatedField() + default_image_url = serializers.ImageField(source='default_image.image', + allow_null=True) class Meta: """Meta class.""" @@ -107,6 +109,7 @@ class EstablishmentTypeBaseSerializer(serializers.ModelSerializer): 'name_translated', 'use_subtypes', 'index_name', + 'default_image_url', ] extra_kwargs = { 'name': {'write_only': True}, @@ -129,8 +132,9 @@ class EstablishmentTypeGeoSerializer(EstablishmentTypeBaseSerializer): class EstablishmentSubTypeBaseSerializer(serializers.ModelSerializer): """Serializer for EstablishmentSubType models.""" - name_translated = TranslatedField() + default_image_url = serializers.ImageField(source='default_image.image', + allow_null=True) class Meta: """Meta class.""" @@ -141,6 +145,7 @@ class EstablishmentSubTypeBaseSerializer(serializers.ModelSerializer): 'name_translated', 'establishment_type', 'index_name', + 'default_image_url', ] extra_kwargs = { 'name': {'write_only': True}, diff --git a/apps/gallery/models.py b/apps/gallery/models.py index 22c5b5e7..0cc8c60e 100644 --- a/apps/gallery/models.py +++ b/apps/gallery/models.py @@ -1,6 +1,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from sorl.thumbnail import delete +from sorl import thumbnail from sorl.thumbnail.fields import ImageField as SORLImageField from utils.methods import image_path @@ -47,7 +47,7 @@ class Image(ProjectBaseMixin, SORLImageMixin, PlatformMixin): """ try: # Delete from remote storage - delete(file_=self.image.file, delete_file=completely) + thumbnail.delete(file_=self.image.file, delete_file=completely) except FileNotFoundError: pass finally: diff --git a/apps/product/migrations/0022_auto_20191220_1007.py b/apps/product/migrations/0022_auto_20191220_1007.py new file mode 100644 index 00000000..c99b0e37 --- /dev/null +++ b/apps/product/migrations/0022_auto_20191220_1007.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.7 on 2019-12-20 10:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('gallery', '0007_auto_20191211_1528'), + ('product', '0021_auto_20191212_0926'), + ] + + operations = [ + migrations.AddField( + model_name='productsubtype', + name='default_image', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='product_sub_types', to='gallery.Image', verbose_name='default image'), + ), + migrations.AddField( + model_name='producttype', + name='default_image', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='product_types', to='gallery.Image', verbose_name='default image'), + ), + ] diff --git a/apps/product/models.py b/apps/product/models.py index 7aeacdf2..3541122b 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -37,6 +37,10 @@ class ProductType(TranslatedFieldsMixin, ProjectBaseMixin): tag_categories = models.ManyToManyField('tag.TagCategory', related_name='product_types', verbose_name=_('Tag categories')) + default_image = models.ForeignKey('gallery.Image', on_delete=models.SET_NULL, + related_name='product_types', + blank=True, null=True, default=None, + verbose_name='default image') class Meta: """Meta class.""" @@ -62,6 +66,10 @@ class ProductSubType(TranslatedFieldsMixin, ProjectBaseMixin): verbose_name=_('Name'), help_text='{"en-GB":"some text"}') index_name = models.CharField(max_length=50, unique=True, db_index=True, verbose_name=_('Index name')) + default_image = models.ForeignKey('gallery.Image', on_delete=models.SET_NULL, + related_name='product_sub_types', + blank=True, null=True, default=None, + verbose_name='default image') class Meta: """Meta class.""" diff --git a/apps/product/serializers/common.py b/apps/product/serializers/common.py index 86344a36..f3678448 100644 --- a/apps/product/serializers/common.py +++ b/apps/product/serializers/common.py @@ -34,6 +34,8 @@ class ProductSubTypeBaseSerializer(serializers.ModelSerializer): name_translated = TranslatedField() index_name_display = serializers.CharField(source='get_index_name_display', read_only=True) + default_image_url = serializers.ImageField(source='default_image.image', + allow_null=True) class Meta: model = models.ProductSubType @@ -41,12 +43,15 @@ class ProductSubTypeBaseSerializer(serializers.ModelSerializer): 'id', 'name_translated', 'index_name_display', + 'default_image_url', ] class ProductTypeBaseSerializer(serializers.ModelSerializer): """ProductType base serializer""" name_translated = TranslatedField() + default_image_url = serializers.ImageField(source='default_image.image', + allow_null=True) class Meta: model = models.ProductType @@ -54,6 +59,7 @@ class ProductTypeBaseSerializer(serializers.ModelSerializer): 'id', 'name_translated', 'index_name', + 'default_image_url', ]