Skip to content

Instantly share code, notes, and snippets.

@renyi
Created August 18, 2012 07:34
Show Gist options
  • Save renyi/3385043 to your computer and use it in GitHub Desktop.
Save renyi/3385043 to your computer and use it in GitHub Desktop.
Simple Geo model for Django
from geopy import units, distance
from mezzanine.core.managers import CurrentSiteManager
class GeoManager(CurrentSiteManager):
def near(self, latitude=None, longitude=None, distance_range=30):
queryset = super(GeoManager, self).get_query_set()
if not (latitude and longitude and distance_range):
return queryset.none()
latitude = float(latitude)
longitude = float(longitude)
distance_range = float(distance_range)
rough_distance = units.degrees(arcminutes=units.nautical(kilometers=distance_range)) * 2
queryset = queryset.filter(
latitude__range=(
latitude - rough_distance,
latitude + rough_distance
),
longitude__range=(
longitude - rough_distance,
longitude + rough_distance
)
)
locations = []
for location in queryset:
if location.latitude and location.longitude:
exact_distance = distance.distance(
(latitude, longitude),
(location.latitude, location.longitude)
).kilometers
if exact_distance <= distance_range:
locations.append(location)
queryset = queryset.filter(id__in=[l.id for l in locations])
return queryset
from geopy import geocoders
from geopy.geocoders.google import GQueryError
class BaseGeo(models.Model):
location = models.TextField(_('Address'), blank=True)
latitude = models.FloatField(_('Latitude'), blank=True, null=True)
longitude = models.FloatField(_('Longitude'), blank=True, null=True)
place = models.TextField(_('Place'), blank=True)
objects = GeoManager()
class Meta:
abstract = True
def save(self, domain='maps.google.com.my', *args, **kwargs):
location = self.location
if location:
if not self.latitude or not self.longitude:
try:
g = geocoders.Google(domain=domain)
self.place, (self.latitude, self.longitude) = g.geocode(location)
except GQueryError:
pass
except Exception, e:
print '%s' % e
super(BaseGeo, self).save(*args, **kwargs)
@jordanmkoncz
Copy link

jordanmkoncz commented Jan 3, 2017

@renyi Thanks for this gist, I needed to implement functionality to find nearby places to a user's address (with latitude/longitude being known for all the places and also the user's address) and this example was very useful!

In my case I wasn't using Mezzanine or anything like that, but I did end up implementing this functionality as a nearby() function on my Place model manager, allowing me to do nearby_places = Place.objects.nearby(latitude=address.latitude, longitude=address.longitude).

@josejaguirre
Copy link

Good solution, thanks for sharing !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment