How to filter a django model with latitude and longitude coordinates that fall within a certain radius

元气小坏坏 提交于 2019-12-03 06:33:04

But you can always make proposed by Brian approach better by filtering the results from previous step (which hoepfully should be smaller subset) and for each you check either they are within the radius.

Your user is in black point. Square approximation given by Brian return green but also orange points. The divernce in distance can be significant in worst case user have to go sqrt(2) times further than expected (extra 40% of distance). So for all orange and green points it is worth to check if their distance from black point (e.g euclidian one if this are really short distances e.g navigation in city) is not greater than assumed radius.

UPDATE:

If you would like to use Haversine distance or (better) mentioned GeoDjango hava a look on this snippet comparing two django views dealing with nearby search:

https://gist.github.com/andilabs/4232b463e5ad2f19c155

You can do range queries with filter.

LocationsNearMe = Location.objects.filter(latitude__gte=(the minimal lat from distance()),
                                          latitude__lte=(the minimal lat from distance()),
                                          (repeat for longitude))

Unfortunately, this returns results in the form of a geometric square (instead of a circle)

If you don't want to use GeoDjango, then you could consider writing it out with Django's Database functions. In contrast to raw SQL, this also gives you the advantage of being able to easily append/prepend other ORM filters.

from django.db.models.functions import Radians, Power, Sin, Cos, ATan2, Sqrt, Radians
from django.db.models import F

dlat = Radians(F('latitude') - current_lat)
dlong = Radians(F('longitude') - current_long)

a = (Power(Sin(dlat/2), 2) + Cos(Radians(current_lat)) 
    * Cos(Radians(F('latitude'))) * Power(Sin(dlong/2), 2)
)

c = 2 * ATan2(Sqrt(a), Sqrt(1-a))
d = 6371 * c

LocationsNearMe = Location.objects.annotate(distance=d).order_by('distance').filter(distance__lt=10)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!