from django.contrib.contenttypes.models import ContentType from django.db.models import QuerySet from typing import Optional, Tuple class LocationMixin: """Mixin for models that can have location data attached.""" def get_location(self) -> Optional['Location']: """Get location for this instance.""" from location.models import Location ct = ContentType.objects.get_for_model(self.__class__) return Location.objects.filter(content_type=ct, object_id=self.pk).first() def set_location(self, address: str, latitude: float, longitude: float) -> 'Location': """Set or update location for this instance.""" from location.models import Location ct = ContentType.objects.get_for_model(self.__class__) location, created = Location.objects.update_or_create( content_type=ct, object_id=self.pk, defaults={ 'address': address, 'latitude': latitude, 'longitude': longitude } ) return location @property def coordinates(self) -> Optional[Tuple[float, float]]: """Get coordinates (latitude, longitude) if available.""" location = self.get_location() if location: return location.latitude, location.longitude return None @property def formatted_location(self) -> str: """Get formatted address string if available.""" location = self.get_location() if location: return location.get_formatted_address() return ""