from django.conf import settings from django.contrib.gis.geos import Point from rest_framework import serializers from location import models from transfer.mixins import TransferSerializerMixin from utils.methods import get_point_from_coordinates from transfer.models import Cepages from django.utils.text import slugify from django.contrib.gis.geos import Point from django.core.exceptions import MultipleObjectsReturned from gallery.models import Image class CountrySerializer(serializers.ModelSerializer): country_code_2 = serializers.CharField() id = serializers.IntegerField() class Meta: model = models.Country fields = ( "id", "country_code_2", ) def validate(self, data): data["code"] = self.get_country_code(data) del (data['country_code_2']) data['old_id'] = data.pop('id') return data def create(self, validated_data): # Some countries already in database try: country = models.Country.objects.get(code=validated_data['code']) except models.Country.DoesNotExist: country = models.Country.objects.create(**validated_data) return country def get_country_code(self, obj): return obj.get("country_code_2") class RegionSerializer(serializers.ModelSerializer): region_code = serializers.CharField() subregion_code = serializers.CharField(allow_null=True, allow_blank=True) country_code_2 = serializers.CharField() id = serializers.IntegerField() class Meta: model = models.Region fields = ( "region_code", "country_code_2", "subregion_code", "id" ) def validate(self, data): data = self.set_old_id(data) data = self.set_code(data) data = self.set_country(data) return data def create(self, validated_data): # Some regions may be already in database try: region = models.Region.objects.get(old_id=validated_data['old_id']) except models.Region.DoesNotExist: region = models.Region.objects.create(**validated_data) except Exception as e: raise ValueError(f"REGION ERROR: {validated_data}: {e}") return region def set_code(self, data): if "subregion_code" in data and data["subregion_code"] is not None and data["subregion_code"].strip() != "": try: parent_region = models.Region.objects.filter(code=str(data['region_code'])).first() except Exception as e: raise ValueError(f"Parent region error with {data}: {e}") data['parent_region'] = parent_region data['code'] = data.pop('subregion_code') del (data['region_code']) else: data['code'] = data.pop('region_code') del (data['subregion_code']) return data def set_country(self, data): try: country = models.Country.objects.get(code=data['country_code_2']) except Exception as e: raise ValueError(f"Country error with {data}: {e}") data["country"] = country del (data['country_code_2']) return data def set_old_id(self, data): data['old_id'] = data.pop("id") return data class CitySerializer(serializers.ModelSerializer): country_code_2 = serializers.CharField() region_code = serializers.CharField() subregion_code = serializers.CharField(allow_null=True, allow_blank=True) zip_code = serializers.CharField(allow_null=True, allow_blank=True) is_island = serializers.IntegerField(allow_null=True) name = serializers.CharField() id = serializers.IntegerField() class Meta: model = models.City fields = ( "country_code_2", "region_code", "subregion_code", "zip_code", "is_island", "name", "id" ) def validate(self, data): data = self.set_old_id(data) data = self.set_relations(data) data = self.set_is_island(data) data = self.set_code(data) data = self.set_zip_code(data) return data def create(self, validated_data): return models.City.objects.create(**validated_data) def set_is_island(self, data): data['is_island'] = True if "is_island" in data \ and data['is_island'] is not None \ and data['is_island'] > 0 \ else False return data def set_code(self, data): data['code'] = data.pop('region_code') return data def set_relations(self, data): try: region = models.Region.objects.filter(code=data['region_code']).first() except models.Region.DoesNotExist as e: try: region = models.Region.objects.filter(code=data['subregion_code']).first() except models.Region.DoesNotExist as e: raise ValueError(f"Region not found with {data}: {e}") data['region'] = region del (data['subregion_code']) try: country = models.Country.objects.get(code=data['country_code_2']) except models.Country.DoesNotExist as e: raise ValueError(f"Country not found with {data}: {e}") data['country'] = country del (data['country_code_2']) return data def set_zip_code(self, data): data['postal_code'] = data.pop('zip_code') if data['postal_code'] is None: data['postal_code'] = "" return data def set_old_id(self, data): data['old_id'] = data.pop('id') return data class AddressSerializer(serializers.ModelSerializer): id = serializers.IntegerField() city_id = serializers.IntegerField() zip_code = serializers.CharField(allow_null=True, allow_blank=True) latitude = serializers.DecimalField(max_digits=10, decimal_places=6, allow_null=True) longitude = serializers.DecimalField(max_digits=10, decimal_places=6, allow_null=True) address = serializers.CharField(allow_null=True, allow_blank=True) class Meta: model = models.Address fields = ( "id", "city_id", "zip_code", "latitude", "longitude", "address" ) def validate(self, data): data = self.set_old_id(data) data = self.set_address(data) data = self.set_postal_code(data) data = self.set_city(data) data = self.set_point(data) return data def create(self, validated_data): return models.Address.objects.create(**validated_data) def set_old_id(self, data): data['old_id'] = data.pop("id") return data def set_postal_code(self, data): data['postal_code'] = data.pop('zip_code', None) if data['postal_code'] is None: data['postal_code'] = "" return data def set_city(self, data): city = models.City.objects.filter(mysql_id=data['city_id']).first() if not city: raise ValueError(f"City not found with ID {data['city_id']}") data['city_id'] = city.id return data def set_address(self, data): if "address" in data and data['address'] is not None and data['address'] != "": address_list = data.pop('address').split(' ') is_first_street = False data['street_name_1'] = [] data['street_name_2'] = [] while len(address_list) > 0: address_part = address_list.pop() try: address_part = int(address_part) data['number'] = address_part is_first_street = True except: if is_first_street: data['street_name_1'].append(address_part) else: data['street_name_2'].append(address_part) data['street_name_1'] = " ".join(data['street_name_1']) data['street_name_2'] = " ".join(data['street_name_2']) if "number" not in data: data['number'] = 0 else: del (data['address']) data['number'] = 0 return data def set_point(self, data): if data['latitude'] is not None and data['longitude'] is not None: data['coordinates'] = Point(float(data['longitude']), float(data['latitude'])) # data['coordinates'] = GEOSGeometry( # json.dumps({ # "type": "Point", # "coordinates": [data['longitude'], data['latitude']] # }, ensure_ascii=False, default=str) # ) else: data['coordinates'] = None del (data['latitude']) del (data['longitude']) return data class WineRegionSerializer(TransferSerializerMixin): id = serializers.IntegerField() name = serializers.CharField() desc = serializers.CharField(allow_null=True) latitude = serializers.FloatField(allow_null=True) longitude = serializers.FloatField(allow_null=True) class Meta: model = models.WineRegion fields = ( 'id', 'name', 'desc', 'latitude', 'longitude', ) def validate(self, attrs): latitude = attrs.pop('latitude', None) longitude = attrs.pop('longitude', None) attrs['old_id'] = attrs.pop('id') attrs['description'] = {settings.FALLBACK_LOCALE: attrs.pop('desc', None)} attrs['coordinates'] = get_point_from_coordinates(latitude, longitude) return attrs class WineSubRegionSerializer(WineRegionSerializer): id = serializers.IntegerField() name = serializers.CharField() parent_id = serializers.IntegerField() class Meta: model = models.WineSubRegion fields = ( 'id', 'name', 'parent_id', ) def validate(self, attrs): parent_id = attrs.pop('parent_id', None) attrs['old_id'] = attrs.pop('id') attrs['wine_region'] = self.get_wine_region(parent_id) return attrs def get_wine_region(self, parent_id): qs = models.WineRegion.objects.filter(old_id=parent_id) if qs.exists(): return qs.first() class WineVillageSerializer(TransferSerializerMixin): id = serializers.IntegerField() name = serializers.CharField() parent_id = serializers.IntegerField() class Meta: model = models.WineVillage fields = ( 'id', 'name', 'parent_id', ) def validate(self, attrs): parent_id = attrs.pop('parent_id', None) attrs['old_id'] = attrs.pop('id') attrs['wine_region'] = self.get_wine_region(parent_id) return attrs class CityMapSerializer(serializers.ModelSerializer): id = serializers.IntegerField() map1 = serializers.CharField(allow_blank=True, allow_null=True) map2 = serializers.CharField(allow_blank=True, allow_null=True) map_ref = serializers.CharField(allow_blank=True, allow_null=True) situation = serializers.CharField(allow_blank=True, allow_null=True) class Meta: model = models.City fields = ( "id", "map1", "map2", "map_ref", "situation", ) def validate(self, data): data = self.set_old_id(data) data = self.set_city(data) data = self.set_null_fields(data) return data def create(self, validated_data): city = validated_data.pop('city') city.update( map1=validated_data['map1'], map2=validated_data['map2'], map_ref=validated_data['map_ref'], situation=validated_data['situation'] ) def set_old_id(self, data): data['old_id'] = data.pop("id") return data def set_city(self, data): try: city = models.City.objects.get(old_id=data['old_id']) except models.City.DoesNotExist as e: raise ValueError(f"Cannot find city with id = {data['old_id']}: {e}") except MultipleObjectsReturned as e: raise ValueError(f"Find multiple cities with id = {data['old_id']}: {e}") data['city'] = city return data def set_null_fields(self, data): for field in ["map1", "map2", "map_ref", "situation"]: if field not in data or data[field] is None: data[field] = "" return data class CityMapCorrectSerializer(CityMapSerializer): def set_city(self, data): try: city = models.City.objects.get(mysql_id=data['old_id']) except models.City.DoesNotExist as e: raise ValueError(f"Cannot find city with id = {data['old_id']}: {e}") except MultipleObjectsReturned as e: raise ValueError(f"Find multiple cities with id = {data['old_id']}: {e}") data['city'] = city return data def create(self, validated_data): city = validated_data.pop('city') city.map1 = validated_data['map1'], city.map2 = validated_data['map2'], city.map_ref = validated_data['map_ref'], city.situation = validated_data['situation'] city.save() class CepageWineRegionSerializer(TransferSerializerMixin): CATEGORY_LABEL = 'Cepage' CATEGORY_INDEX_NAME = slugify(CATEGORY_LABEL) cepage_id = serializers.PrimaryKeyRelatedField( queryset=Cepages.objects.all()) wine_region_id = serializers.IntegerField() class Meta(WineRegionSerializer.Meta): fields = [ 'cepage_id', 'wine_region_id', ] def create(self, validated_data): obj = self.get_wine_region(validated_data['wine_region_id']) cepage = validated_data.get('cepage_id') tag = self.get_tag(cepage.name, self.CATEGORY_INDEX_NAME) if obj and tag not in obj.tags.all(): obj.tags.add(tag) return obj