Skip to content

Instantly share code, notes, and snippets.

@bimusiek
Created February 28, 2015 22:05
Show Gist options
  • Save bimusiek/7d23cae40ebab4fd823f to your computer and use it in GitHub Desktop.
Save bimusiek/7d23cae40ebab4fd823f to your computer and use it in GitHub Desktop.
Closest location (lat & long) with Postgresql in Django

Distance calculation

Example how to calculate distance and then take closest location.

Can be further imporved by first filtering locations to some square withing min & max lat & long. So we are not calculating distance for all locations.

I know you could use some greate Geo engine for PostgreSQL or Django but I needed fast, working solution. Feel free to use

License

MIT

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('locations', '0001_initial'),
]
operations = [
migrations.RunSQL("""
CREATE OR REPLACE FUNCTION distance(lat1 FLOAT, lon1 FLOAT, lat2 FLOAT, lon2 FLOAT) RETURNS FLOAT AS $$
DECLARE
x float = 69.1 * (lat2 - lat1);\
y float = 69.1 * (lon2 - lon1) * cos(lat1 / 57.3);\
BEGIN
RETURN sqrt(x * x + y * y);\
END
$$ LANGUAGE plpgsql;\
""")
]
from django.db.models.base import Model
from django.db.models.fields import CharField, IntegerField, DecimalField
from django_extensions.db.fields.json import JSONField
class LocationModel(Model):
name = CharField(max_length=255)
english_name = CharField(max_length=255)
country = CharField(max_length=255)
location_id = IntegerField(primary_key=True)
lat = DecimalField(max_digits=20, decimal_places=10)
long = DecimalField(max_digits=20, decimal_places=10)
viewport = JSONField()
@classmethod
def closest(cls, lat, long):
locations = LocationModel.objects.extra(
select={
'distance': 'distance(lat, long, %f, %f)' % (lat, long)
}
)
locations = locations.order_by('distance')
return locations.first()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment