# from django.contrib.gis.db import models # Disabled temporarily for setup from django.db import models # from django.contrib.gis.geos import Point # Disabled temporarily for setup import pghistory @pghistory.track() class ParkLocation(models.Model): """ Represents the geographic location and address of a park, with PostGIS support. """ park = models.OneToOneField( "parks.Park", on_delete=models.CASCADE, related_name="location" ) # Spatial Data - Temporarily disabled for setup # point = models.PointField( # srid=4326, # null=True, # blank=True, # help_text="Geographic coordinates (longitude, latitude)", # ) point = models.CharField(max_length=50, null=True, blank=True) # Temporary placeholder # Address Fields street_address = models.CharField(max_length=255, blank=True) city = models.CharField(max_length=100, db_index=True) state = models.CharField(max_length=100, db_index=True) country = models.CharField(max_length=100, default="USA") continent = models.CharField( max_length=50, blank=True, db_index=True, help_text="Continent where the park is located" ) postal_code = models.CharField(max_length=20, blank=True) # Road Trip Metadata highway_exit = models.CharField(max_length=100, blank=True) parking_notes = models.TextField(blank=True) best_arrival_time = models.TimeField(null=True, blank=True) seasonal_notes = models.TextField(blank=True) # OSM Integration osm_id = models.BigIntegerField(null=True, blank=True) osm_type = models.CharField( max_length=10, blank=True, help_text="Type of OpenStreetMap object (node, way, or relation)", ) @property def latitude(self): """Return latitude from point field.""" if self.point: return self.point.y return None @property def longitude(self): """Return longitude from point field.""" if self.point: return self.point.x return None @property def coordinates(self): """Return (latitude, longitude) tuple.""" if self.point: return (self.latitude, self.longitude) return (None, None) @property def formatted_address(self): """Return a nicely formatted address string.""" address_parts = [ self.street_address, self.city, self.state, self.postal_code, self.country, ] return ", ".join(part for part in address_parts if part) def set_coordinates(self, latitude, longitude): """ Set the location's point from latitude and longitude coordinates. Validates coordinate ranges. """ if latitude is None or longitude is None: self.point = None return if not -90 <= latitude <= 90: raise ValueError("Latitude must be between -90 and 90.") if not -180 <= longitude <= 180: raise ValueError("Longitude must be between -180 and 180.") self.point = Point(longitude, latitude, srid=4326) def distance_to(self, other_location): """ Calculate the distance to another ParkLocation instance. Returns distance in kilometers. """ if not self.point or not other_location.point: return None # Use geodetic distance calculation which returns meters, convert to km distance_m = self.point.distance(other_location.point) return distance_m / 1000.0 def __str__(self): return f"Location for {self.park.name}" class Meta: verbose_name = "Park Location" verbose_name_plural = "Park Locations" ordering = ["park__name"] indexes = [ models.Index(fields=["city", "state"]), ]