diff --git a/apps/gallery/migrations/0007_auto_20191110_1329.py b/apps/gallery/migrations/0007_auto_20191110_1329.py new file mode 100644 index 00000000..fd1771ed --- /dev/null +++ b/apps/gallery/migrations/0007_auto_20191110_1329.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.4 on 2019-11-10 13:29 + +from django.db import migrations +import sorl.thumbnail.fields +import utils.methods + + +class Migration(migrations.Migration): + + dependencies = [ + ('gallery', '0006_merge_20191027_1758'), + ] + + operations = [ + migrations.AlterField( + model_name='image', + name='image', + field=sorl.thumbnail.fields.ImageField(max_length=255, upload_to=utils.methods.image_path, verbose_name='image file'), + ), + ] diff --git a/apps/gallery/models.py b/apps/gallery/models.py index baed48fc..ba0c28b3 100644 --- a/apps/gallery/models.py +++ b/apps/gallery/models.py @@ -22,7 +22,7 @@ class Image(ProjectBaseMixin, SORLImageMixin, PlatformMixin): ) image = SORLImageField(upload_to=image_path, - verbose_name=_('image file')) + verbose_name=_('image file'), max_length=255) orientation = models.PositiveSmallIntegerField(choices=ORIENTATIONS, blank=True, null=True, default=None, verbose_name=_('image orientation')) diff --git a/apps/location/migrations/0027_auto_20191110_1331.py b/apps/location/migrations/0027_auto_20191110_1331.py new file mode 100644 index 00000000..3a1af228 --- /dev/null +++ b/apps/location/migrations/0027_auto_20191110_1331.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.4 on 2019-11-10 13:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('location', '0026_auto_20191107_2010'), + ] + + operations = [ + migrations.AddField( + model_name='citygallery', + name='old_id', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='city', + name='gallery', + field=models.ManyToManyField(blank=True, through='location.CityGallery', to='gallery.Image'), + ), + ] diff --git a/apps/location/models.py b/apps/location/models.py index 67385dc2..2ddf5950 100644 --- a/apps/location/models.py +++ b/apps/location/models.py @@ -130,6 +130,7 @@ class CityGalleryQuerySet(models.QuerySet): class CityGallery(models.Model): + old_id = models.IntegerField(blank=True, null=True) city = models.ForeignKey(City, null=True, related_name='city_gallery', on_delete=models.CASCADE, diff --git a/apps/location/serializers/common.py b/apps/location/serializers/common.py index 36163e12..0254051b 100644 --- a/apps/location/serializers/common.py +++ b/apps/location/serializers/common.py @@ -60,51 +60,36 @@ class RegionSerializer(serializers.ModelSerializer): class CropImageSerializer(serializers.Serializer): """Serializer for crop images for City object.""" - preview_url = serializers.SerializerMethodField() - promo_horizontal_web_url = serializers.SerializerMethodField() - promo_horizontal_mobile_url = serializers.SerializerMethodField() - tile_horizontal_web_url = serializers.SerializerMethodField() - tile_horizontal_mobile_url = serializers.SerializerMethodField() - tile_vertical_web_url = serializers.SerializerMethodField() - highlight_vertical_web_url = serializers.SerializerMethodField() - editor_web_url = serializers.SerializerMethodField() - editor_mobile_url = serializers.SerializerMethodField() + xsmall_url = serializers.SerializerMethodField() + small_url = serializers.SerializerMethodField() + medium_url = serializers.SerializerMethodField() + large_url = serializers.SerializerMethodField() + xlarge_url = serializers.SerializerMethodField() + detail_url = serializers.SerializerMethodField() - def get_preview_url(self, obj): + def get_xsmall_url(self, obj): """Get crop preview.""" - return obj.instance.get_image_url('news_preview') + return obj.instance.get_image_url('location_city_xsmall') - def get_promo_horizontal_web_url(self, obj): - """Get crop promo_horizontal_web.""" - return obj.instance.get_image_url('news_promo_horizontal_web') + def get_small_url(self, obj): + """Get crop preview.""" + return obj.instance.get_image_url('location_city_small') - def get_promo_horizontal_mobile_url(self, obj): - """Get crop promo_horizontal_mobile.""" - return obj.instance.get_image_url('news_promo_horizontal_mobile') + def get_medium_url(self, obj): + """Get crop preview.""" + return obj.instance.get_image_url('location_city_medium') - def get_tile_horizontal_web_url(self, obj): - """Get crop tile_horizontal_web.""" - return obj.instance.get_image_url('news_tile_horizontal_web') + def get_large_url(self, obj): + """Get crop preview.""" + return obj.instance.get_image_url('location_city_large') - def get_tile_horizontal_mobile_url(self, obj): - """Get crop tile_horizontal_mobile.""" - return obj.instance.get_image_url('news_tile_horizontal_mobile') + def get_xlarge_url(self, obj): + """Get crop preview.""" + return obj.instance.get_image_url('location_city_xlarge') - def get_tile_vertical_web_url(self, obj): - """Get crop tile_vertical_web.""" - return obj.instance.get_image_url('news_tile_vertical_web') - - def get_highlight_vertical_web_url(self, obj): - """Get crop highlight_vertical_web.""" - return obj.instance.get_image_url('news_highlight_vertical_web') - - def get_editor_web_url(self, obj): - """Get crop editor_web.""" - return obj.instance.get_image_url('news_editor_web') - - def get_editor_mobile_url(self, obj): - """Get crop editor_mobile.""" - return obj.instance.get_image_url('news_editor_mobile') + def get_detail_url(self, obj): + """Get crop preview.""" + return obj.instance.get_image_url('location_city_detail') class CityImageSerializer(serializers.ModelSerializer): diff --git a/apps/location/transfer_data.py b/apps/location/transfer_data.py index e79135ad..ca34f987 100644 --- a/apps/location/transfer_data.py +++ b/apps/location/transfer_data.py @@ -1,7 +1,7 @@ from transfer.serializers.location import CountrySerializer, RegionSerializer, \ - CitySerializer, AddressSerializer, CityMapSerializer, \ + CitySerializer, AddressSerializer, CityMapSerializer, CityGallerySerializer, \ Country -from transfer.models import Cities, Locations +from transfer.models import Cities, Locations, CityPhotos from pprint import pprint from requests import get @@ -162,6 +162,29 @@ def migrate_city_map_situation(): pprint(f"City info serializer errors: {serialized_data.errors}") +def migrate_city_photos(): + queryset = CityPhotos.objects.raw("""SELECT city_photos.id, city_photos.city_id, city_photos.attachment_file_name + FROM city_photos WHERE + city_photos.attachment_file_name IS NOT NULL AND + city_id IN( + SELECT cities.id + FROM cities WHERE + region_code IS NOT NULL AND + region_code != "" AND + country_code_2 IS NOT NULL AND + country_code_2 != "" + ) + """) + + queryset = [vars(query) for query in queryset] + + serialized_data = CityGallerySerializer(data=queryset, many=True) + if serialized_data.is_valid(): + serialized_data.save() + else: + pprint(f"Address serializer errors: {serialized_data.errors}") + + data_types = { "dictionaries": [ transfer_countries, @@ -173,7 +196,10 @@ data_types = { update_flags ], "update_city_info": [ - migrate_city_map_situation() + migrate_city_map_situation + ], + "migrate_city_gallery": [ + migrate_city_photos ] } diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index 77ed7e4c..95afd068 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -29,7 +29,8 @@ class Command(BaseCommand): LONG_DATA_TYPES = [ 'update_country_flag', 'comment', - 'update_city_info' + 'update_city_info', + 'migrate_city_gallery' ] def handle(self, *args, **options): diff --git a/apps/transfer/serializers/location.py b/apps/transfer/serializers/location.py index 5ce82d4f..d54ffb32 100644 --- a/apps/transfer/serializers/location.py +++ b/apps/transfer/serializers/location.py @@ -1,7 +1,8 @@ from rest_framework import serializers -from location.models import Country, Region, City, Address +from location.models import Country, Region, City, Address, CityGallery from django.contrib.gis.geos import Point from django.core.exceptions import MultipleObjectsReturned +from gallery.models import Image class CountrySerializer(serializers.ModelSerializer): @@ -310,7 +311,6 @@ class CityMapSerializer(serializers.ModelSerializer): except MultipleObjectsReturned as e: raise ValueError(f"Find multiple cities with id = {data['old_id']}: {e}") - data['city'] = city return data @@ -319,3 +319,47 @@ class CityMapSerializer(serializers.ModelSerializer): if field not in data or data[field] is None: data[field] = "" return data + + +class CityGallerySerializer(serializers.ModelSerializer): + id = serializers.IntegerField() + city_id = serializers.IntegerField() + attachment_file_name = serializers.CharField() + + class Meta: + model = CityGallery + fields = ("id", "city_id", "attachment_file_name") + + def validate(self, data): + data = self.set_old_id(data) + data = self.set_gallery(data) + data = self.set_city(data) + return data + + def create(self, validated_data): + return CityGallery.objects.create(**validated_data) + + def set_old_id(self, data): + data['old_id'] = data.pop('id') + return data + + def set_gallery(self, data): + link_prefix = "city_photos/00baf486523f62cdf131fa1b19c5df2bf21fc9f8/" + try: + data['image'] = Image.objects.create( + image=f"{link_prefix}{data['attachment_file_name']}" + ) + except Exception as e: + raise ValueError(f"Cannot create image with {data}: {e}") + del(data['attachment_file_name']) + return data + + def set_city(self, data): + try: + data['city'] = City.objects.get(old_id=data.pop('city_id')) + except City.DoesNotExist as e: + raise ValueError(f"Cannot get city with {data}: {e}") + except MultipleObjectsReturned as e: + raise ValueError(f"Multiple cities find with {data}: {e}") + + return data diff --git a/project/settings/base.py b/project/settings/base.py index 41233560..d2e30430 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -157,16 +157,16 @@ DATABASES = { 'HOST': os.environ.get('DB_HOSTNAME'), 'PORT': os.environ.get('DB_PORT'), }, - # 'legacy': { - # 'ENGINE': 'django.db.backends.mysql', - # # 'HOST': '172.17.0.1', - # # 'HOST': '172.23.0.1', - # 'HOST': 'mysql_db', - # 'PORT': 3306, - # 'NAME': 'dev', - # 'USER': 'dev', - # 'PASSWORD': 'octosecret123' - # } + 'legacy': { + 'ENGINE': 'django.db.backends.mysql', + 'HOST': '172.17.0.1', + # 'HOST': '172.23.0.1', + # 'HOST': 'mysql_db', + 'PORT': 3306, + 'NAME': 'dev', + 'USER': 'dev', + 'PASSWORD': 'octosecret123' + } } @@ -361,6 +361,13 @@ THUMBNAIL_ALIASES = { 'news_editor_web': {'size': (940, 430), }, # при загрузке через контент эдитор 'news_editor_mobile': {'size': (343, 260), }, # через контент эдитор в мобильном браузерe 'avatar_comments_web': {'size': (116, 116), }, + # location.city + 'location_city_xsmall': {'size': (70, 70), }, + 'location_city_small': {'size': (140, 140), }, + 'location_city_medium': {'size': (280, 280), }, + 'location_city_large': {'size': (280, 280), }, + 'location_city_xlarge': {'size': (560, 560), }, + 'location_city_detail': {'size': (1120, 1120), }, } }