cyberhawk
cyberhawk

Reputation: 11

How to do location based query with simple Django filter?

I've saved user's coordinates in the User model. Post model has latitude, longitude and radius field. Only the users in that vicinity(of Post) will be able to see that post. I don't know how to use filter() here so I used the following approach:

post=Posts.objects.all()
for a in post:
    distance= geopy.distance.geodesic((lat1,lng1), (a.latitude, a.longitude)).km
    print(distance)
    if distance < a.radius:
        p.append(a)    
    else:
        continue

Here, lat1 and lng1 are the coordinates of current User. Suggest if there is any better way as this seems very inefficient.

Upvotes: 0

Views: 678

Answers (1)

C14L
C14L

Reputation: 12548

Depending on your requirements, you could use a square instead of a circle. Pre-calculate the x-max, x-min, y-max and y-min boundaries for your square and then do a simple User.filter(lat__gt=lat_min, user.lng__gt=lng_min, user.lat__lt=lat_max ... lookup in the database.

In a past project, I used this:

def get_latlng_bounderies(lat, lng, distance):
    """
    Return min/max lat/lng values for a distance around a latlng.
    :lat:, :lng: the center of the area.
    :distance: in km, the "radius" around the center point.
    :returns: Two corner points of a square that countains the circle,
              lat_min, lng_min, lat_max, lng_max.
    """
    gc = great_circle(kilometers=distance)
    p0 = gc.destination((lat, lng), 0)
    p90 = gc.destination((lat, lng), 90)
    p180 = gc.destination((lat, lng), 180)
    p270 = gc.destination((lat, lng), 270)

    ret = p180[0], p270[1], p0[0], p90[1]
    return ret

Its not a circle, so its not exact around the "corners" of the square, but its much faster, because its a simple float comparision in the database.

Upvotes: 1

Related Questions