From 0fb28467fbb99fa51a2ebf2cf5bc8afcac2b5d29 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 29 Nov 2019 13:26:05 +0300 Subject: [PATCH] updated serializer --- _dockerfiles/db/Dockerfile | 2 +- apps/location/models.py | 2 +- apps/transfer/serializers/guide.py | 207 ++++++++++++++++++----------- 3 files changed, 133 insertions(+), 78 deletions(-) diff --git a/_dockerfiles/db/Dockerfile b/_dockerfiles/db/Dockerfile index 45c707d9..e8a9ded3 100644 --- a/_dockerfiles/db/Dockerfile +++ b/_dockerfiles/db/Dockerfile @@ -1,3 +1,3 @@ -FROM mdillon/postgis:9.5 +FROM mdillon/postgis:latest RUN localedef -i ru_RU -c -f UTF-8 -A /usr/share/locale/locale.alias ru_RU.UTF-8 ENV LANG ru_RU.utf8 diff --git a/apps/location/models.py b/apps/location/models.py index 3f104644..50f09b92 100644 --- a/apps/location/models.py +++ b/apps/location/models.py @@ -197,7 +197,7 @@ class WineRegionQuerySet(models.QuerySet): return self.exclude(wines__isnull=value) -class WineRegion(models.Model, TranslatedFieldsMixin): +class WineRegion(TranslatedFieldsMixin, models.Model): """Wine region model.""" name = models.CharField(_('name'), max_length=255) country = models.ForeignKey(Country, on_delete=models.PROTECT, diff --git a/apps/transfer/serializers/guide.py b/apps/transfer/serializers/guide.py index 5accbe64..692ebedc 100644 --- a/apps/transfer/serializers/guide.py +++ b/apps/transfer/serializers/guide.py @@ -6,9 +6,11 @@ from rest_framework import serializers from collection.models import Guide, GuideType, GuideFilter from establishment.models import EstablishmentType -from location.models import Country, Region +from location.models import Country, Region, WineRegion from main.models import SiteSettings from transfer.mixins import TransferSerializerMixin +from translation.models import Language +from review.models import Review class GuideSerializer(TransferSerializerMixin): @@ -70,9 +72,6 @@ class GuideFilterSerializer(TransferSerializerMixin): regions = serializers.CharField(allow_null=True) subregions = serializers.CharField(allow_null=True) wine_regions = serializers.CharField(allow_null=True) - wine_classifications = serializers.CharField(allow_null=True) - wine_colors = serializers.CharField(allow_null=True) - wine_types = serializers.CharField(allow_null=True) locales = serializers.CharField(allow_null=True) states = serializers.CharField(allow_null=True) @@ -91,9 +90,6 @@ class GuideFilterSerializer(TransferSerializerMixin): 'regions', 'subregions', 'wine_regions', - 'wine_classifications', - 'wine_colors', - 'wine_types', 'max_mark', 'min_mark', 'marks_only', @@ -112,12 +108,6 @@ class GuideFilterSerializer(TransferSerializerMixin): loader.add_constructor('!ruby/hash:ActiveSupport::HashWithIndifferentAccess', convert_entry) return yaml.load(raw_value, Loader=loader) if raw_value else None - @staticmethod - def get_country_alpha_2(country_code_alpha3: str): - country = countries.get(alpha_3=country_code_alpha3.upper()) - return {'code_alpha_2': country.alpha2.lower() if country else None, - 'name': country.name if country else None,} - @staticmethod def parse_dictionary(dictionary: dict): """ @@ -140,19 +130,20 @@ class GuideFilterSerializer(TransferSerializerMixin): return list(chain.from_iterable(l)) def get_country(self, code_alpha_3: str) -> Country: - country = self.get_country_alpha_2(code_alpha_3) - country_name = country['name'] - country_code = country['code_alpha_2'] - if country_name and country_code: - country, _ = Country.objects.get_or_create( - code__icontains=country_code, - name__contains={'en-GB': country_name}, - defaults={ - 'code': country_code, - 'name': {'en-GB': country_name} - } - ) - return country + country = countries.get(alpha_3=code_alpha_3.upper()) + if country: + country_name = country.name + country_code = country.alpha_2 + if country_name and country_code: + country, _ = Country.objects.get_or_create( + code__icontains=country_code, + name__contains={'en-GB': country_name}, + defaults={ + 'code': country_code, + 'name': {'en-GB': country_name} + } + ) + return country def get_region(self, region_code_alpha_3: str, country_code_alpha_3: str, @@ -162,20 +153,21 @@ class GuideFilterSerializer(TransferSerializerMixin): region_qs = Region.objects.filter(code__iexact=region_code_alpha_3, country__code__iexact=country_code_alpha_2) + if region_qs.exists(): + return region_qs.first() + # If region isn't existed, check sub region for parent_code (region code) - if not region_qs.exists() and sub_region_code_alpha_3: + if sub_region_code_alpha_3: # sub region subdivision = subdivisions.get( code=f"{country_code_alpha_2}-{sub_region_code_alpha_3}") if subdivision: - subdivision_region = subdivisions.get(parent_code=subdivision.parent_code) + subdivision_region = subdivisions.get(code=subdivision.parent_code) obj = Region.objects.create( name=subdivision_region.name, code=subdivision_region.code, country=country) return obj - else: - return region_qs.first() def validate_year(self, value): return self.parse_ruby_helper(value) @@ -189,7 +181,7 @@ class GuideFilterSerializer(TransferSerializerMixin): def validate_regions(self, value): return self.parse_ruby_helper(value) - def validate_sub_regions(self, value): + def validate_subregions(self, value): return self.parse_ruby_helper(value) def validate_wine_regions(self, value): @@ -215,69 +207,132 @@ class GuideFilterSerializer(TransferSerializerMixin): regions = attrs.pop('regions') attrs['old_id'] = attrs.pop('id') - attrs['review_vintage_json'] = self.get_review_vintage(self.attrs.pop('year')) + attrs['review_vintage_json'] = self.get_review_vintage(attrs.pop('year')) attrs['establishment_type_json'] = self.get_establishment_type_ids( - self.attrs.pop('establishment_type')) - attrs['country_code_json'] = self.get_country_ids(attrs.pop('country_json')) - attrs['region_json'] = self.get_region_ids(regions, sub_regions) - attrs['sub_region_json'] = self.get_sub_region_ids(regions, sub_regions) + attrs.pop('establishment_type')) + attrs['country_code_json'] = self.get_country_ids(attrs.pop('countries')) + attrs['region_json'] = self.get_region_ids(regions=regions, + sub_regions=sub_regions) + attrs['sub_region_json'] = self.get_sub_region_ids(sub_regions) + attrs['wine_region_json'] = self.get_wine_region_ids(attrs.pop('wine_regions')) + attrs['with_mark'] = attrs.pop('marks_only') + attrs['locale_json'] = self.get_locale_ids(attrs.pop('locales')) + attrs['review_state_json'] = self.get_review_state(attrs.pop('states')) + attrs['guide'] = self.get_guide(attrs.pop('guide_id')) return attrs def get_review_vintage(self, year): - return {'vintage': [int(i) for i in set(year) if i.isdigit()]} + if hasattr(year, '__iter__'): + return {'vintage': set(int(i) for i in set(year) if i.isdigit())} + return {'vintage': {year}} def get_establishment_type_ids(self, establishment_types): establishment_type_ids = [] - for establishment_type in establishment_types: - establishment_type_qs = EstablishmentType.objects.filter(index_name__iexact=establishment_type) - if not establishment_type_qs.exists(): - obj = EstablishmentType.objects.create( - name={'en-GB': establishment_type.capitalize}, - index_name=establishment_type.lower()) + if establishment_types: + for establishment_type in establishment_types: + establishment_type_qs = EstablishmentType.objects.filter(index_name__iexact=establishment_type) + if not establishment_type_qs.exists(): + obj = EstablishmentType.objects.create( + name={'en-GB': establishment_type.capitalize()}, + index_name=establishment_type.lower()) + else: + obj = establishment_type_qs.first() establishment_type_ids.append(obj.id) - return {'id': establishment_type_ids} + return {'id': set(establishment_type_ids)} def get_country_ids(self, country_codes_alpha_3): country_ids = [] - for code_alpha_3 in country_codes_alpha_3: - country_ids.append(self.get_country(code_alpha_3).id) - return {'id': country_ids} + if country_codes_alpha_3: + for code_alpha_3 in country_codes_alpha_3: + country = self.get_country(code_alpha_3) + if not country: + raise serializers.ValidationError({'detail': f'Country with alpha code 3 -' + f'{code_alpha_3}, is not found.'}) + country_ids.append(country.id) + return {'id': set(country_ids)} def get_region_ids(self, regions, sub_regions): region_ids = [] - for country_code_alpha_3 in regions: - region_codes = regions[country_code_alpha_3] - for region_code_alpha_3 in region_codes: - region = self.get_region( - region_code_alpha_3=region_code_alpha_3, - country_code_alpha_3=country_code_alpha_3, - sub_region_code_alpha_3=sub_regions[country_code_alpha_3][region_code_alpha_3]) - if region: - region_ids.append(region.id) + if regions: + for country_code_alpha_3 in regions: + for region_code_alpha_3 in regions[country_code_alpha_3]: + # Get region from sub region code. + if not sub_regions or country_code_alpha_3 not in sub_regions: + raise serializers.ValidationError({'detail': f'Sub regions is blanked.'}) + if region_code_alpha_3 in sub_regions[country_code_alpha_3]: + for sub_region_code_alpha_3 in sub_regions[country_code_alpha_3][region_code_alpha_3]: + region = self.get_region( + region_code_alpha_3=region_code_alpha_3, + country_code_alpha_3=country_code_alpha_3, + sub_region_code_alpha_3=sub_region_code_alpha_3) + if region: + region_ids.append(region.id) return {'id': region_ids} def get_sub_region_ids(self, sub_regions): sub_region_ids = [] - for country_code_alpha_3 in sub_regions: - for region_code_alpha_3 in sub_regions[country_code_alpha_3]: - region_codes = sub_regions[country_code_alpha_3][region_code_alpha_3] - for sub_region_code_alpha_3 in region_codes: - region = self.get_region( - region_code_alpha_3=region_code_alpha_3, - country_code_alpha_3=country_code_alpha_3, - sub_region_code_alpha_3=sub_region_code_alpha_3) - if region: - subdivision = subdivisions.get(parent_code=region.code.upper()) - if subdivision: - sub_region = Region.objects.create( - name=subdivision.name, - code=subdivisions.code, - parent_region=region, - country=region.country) - sub_region_ids.append(sub_region.id) + if sub_regions: + for country_code_alpha_3 in sub_regions: + # FRA etc. + for region_code_alpha_3 in sub_regions[country_code_alpha_3]: + # B, C, A etc. + for sub_region_code_alpha_3 in sub_regions[country_code_alpha_3][region_code_alpha_3]: + # 24, 32 etc. + # Get parent region + region = self.get_region( + region_code_alpha_3=region_code_alpha_3, + country_code_alpha_3=country_code_alpha_3, + sub_region_code_alpha_3=sub_region_code_alpha_3) + if region: + sub_region_qs = Region.objects.filter(parent_region__code=region.code) + if sub_region_qs.exists(): + sub_region_ids.append(sub_region_qs.first().id) + else: + subdivision = subdivisions.get(code=region.code.upper()) + if subdivision: + sub_region = Region.objects.get_or_create( + name=subdivision.name, + code=subdivisions.parent_code, + parent_region=region, + country=region.country) + sub_region_ids.append(sub_region.id) + return {'id': set(sub_region_ids)} - return {'id': sub_region_ids} + def get_wine_region_ids(self, wine_regions): + wine_region_ids = [] + if wine_regions: + for wine_region in wine_regions: + qs = WineRegion.objects.filter(name__iexact=wine_region) + if not qs.exists(): + raise serializers.ValidationError({ + 'detail': f'Wine region - {wine_region}, is not found.'}) + wine_region_ids.append(qs.first().id) + return {'id': set(wine_region_ids)} + def get_locale_ids(self, locales): + locale_ids = [] + if locales: + for locale in [locale for locale in locales if locale]: + qs = Language.objects.filter(locale=locale) + if not qs.exists(): + raise serializers.ValidationError({ + 'detail': f'{locale} is not found.'}) + return {'id': set(locale_ids)} -# {'FRA': ['H', 'U']} REGIONS -# {'FRA': {'N': ['32']}} SUB REGIONS + def get_review_state(self, states): + review_states = [] + if states: + for state in [state for state in states if state]: + if state == 'published': + review_states.append(Review.READY) + else: + review_states.append(Review.TO_INVESTIGATE) + return {'state': set(review_states)} + + def get_guide(self, old_guide_id: int): + qs = Guide.objects.filter(old_id=old_guide_id) + if not qs.exists(): + raise serializers.ValidationError({'detail': f'Guide with old id - ' + f'{old_guide_id}, ' + f'is not found.'}) + return qs.first()