Filter zipcodes by proximity in Django with the Spherical Law of Cosines

后端 未结 6 959
轮回少年
轮回少年 2020-12-07 21:49

I\'m trying to handle proximity search for a basic store locater in Django. Rather than haul PostGIS around with my app just so I can use GeoDjango\'s distance filter, I\'d

6条回答
  •  天涯浪人
    2020-12-07 22:03

    To follow up on Tom's answer, it won't work in SQLite by default because of SQLite's lack of math functions by default. No problem, it's pretty simple to add:

    class LocationManager(models.Manager):
        def nearby_locations(self, latitude, longitude, radius, max_results=100, use_miles=True):
            if use_miles:
                distance_unit = 3959
            else:
                distance_unit = 6371
    
            from django.db import connection, transaction
            from mysite import settings
            cursor = connection.cursor()
            if settings.DATABASE_ENGINE == 'sqlite3':
                connection.connection.create_function('acos', 1, math.acos)
                connection.connection.create_function('cos', 1, math.cos)
                connection.connection.create_function('radians', 1, math.radians)
                connection.connection.create_function('sin', 1, math.sin)
    
            sql = """SELECT id, (%f * acos( cos( radians(%f) ) * cos( radians( latitude ) ) *
            cos( radians( longitude ) - radians(%f) ) + sin( radians(%f) ) * sin( radians( latitude ) ) ) )
            AS distance FROM location_location WHERE distance < %d
            ORDER BY distance LIMIT 0 , %d;""" % (distance_unit, latitude, longitude, latitude, int(radius), max_results)
            cursor.execute(sql)
            ids = [row[0] for row in cursor.fetchall()]
    
            return self.filter(id__in=ids)
    

提交回复
热议问题