import logging import requests from constance import config from django.contrib.gis.geos import Point from django.db import models logger = logging.getLogger("django.request") class AddressManager(models.Manager): def create(self, raw_data: str, **kwargs): # type: ignore if not raw_data: raise ValueError("'raw_data' (address string) must be provided.") params: dict[str, str | int] = { "format": "json", "addressdetails": 1, "q": raw_data, } resp = requests.get(config.NOMINATIM_URL.rstrip("/") + "/search", params=params) resp.raise_for_status() results = resp.json() if not results: raise ValueError(f"No geocoding result for address: {raw_data}") data = results[0] addr = data.get("address", {}) street = f"{addr.get('road', '') or addr.get('pedestrian', '')}, {addr.get('house_number', '')}" district = addr.get("city_district") or addr.get("suburb") or "" city = addr.get("city") or addr.get("town") or addr.get("village") or "" region = addr.get("state") or addr.get("region") or "" postal_code = addr.get("postcode") or "" country = addr.get("country") or "" try: lat = float(data.get("lat")) lon = float(data.get("lon")) location = Point(lon, lat, srid=4326) except (TypeError, ValueError): location = None try: address_line_1 = kwargs.pop("address_line_1") except KeyError as e: raise ValueError("Missing required field 'address_line_1'") from e try: address_line_2 = kwargs.pop("address_line_2") except KeyError: address_line_2 = "" return super().get_or_create( raw_data=raw_data, address_line=f"{address_line_1}, {address_line_2}", street=street, district=district, city=city, region=region, postal_code=postal_code, country=country, user=kwargs.pop("user"), defaults={"api_response": data, "location": location}, )[0]