from rest_framework import serializers from location.models import Country, Region, City, Address from django.contrib.gis.geos import Point from django.contrib.gis.geos import GEOSGeometry import json class CountrySerializer(serializers.ModelSerializer): country_code_2 = serializers.CharField() id = serializers.IntegerField() class Meta: model = 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 = Country.objects.get(code=validated_data['code']) except Country.DoesNotExist: country = 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 = 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 = Region.objects.get(old_id=validated_data['old_id']) except Region.DoesNotExist: region = Region.objects.create(**validated_data) except Exception as e: raise ValueError(f"REGION ERROR: {validated_data}: {e}") return region def set_code(self, data): print(data) if "subregion_code" in data and data["subregion_code"] is not None and data["subregion_code"].strip() != "": try: parent_region = 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 = 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 = 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 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 = Region.objects.filter(code=data['region_code']).first() except Region.DoesNotExist as e: try: region = Region.objects.filter(code=data['subregion_code']).first() except Region.DoesNotExist as e: raise ValueError(f"Region not found with {data}: {e}") data['region'] = region del(data['subregion_code']) try: country = Country.objects.get(code=data['country_code_2']) except 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() class Meta: model = 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 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): try: city = City.objects.filter(old_id=data['city_id']).first() except City.DoesNotExist as e: raise ValueError(f"City not found with {data}: {e}") data['city'] = city del(data['city_id']) return data def set_address(self, data): 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 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