GeoDjango:我怎样才能得到两点之间的距离?

时间:2015-08-19 10:11:36

标签: python django location distance geodjango

我的Profile模型有这个字段:

location = models.PointField(geography=True, dim=2, srid=4326)

我想使用GeoDjango计算这两个locations之间的距离(考虑到地球是一个椭球体),这样我就可以将这个距离存储在数据库中。

  1. 如何使用GeoDjango计算此距离?
  2. 结果是什么单位?
  3. 有没有最好的'存储这些数据的方法?浮动?小数?
  4. 我已经回顾过以前的类似问题,并且没有发现它们有用。没有答案可以解释发生了什么或者它为什么会起作用。

    我使用Django 1.8和GeoDjango所需的最新版本库。

    谢谢!

3 个答案:

答案 0 :(得分:5)

根据 Abhyudit Jain 的评论,我正在使用geopy来计算距离。根据 e4c5 的建议,我将它添加为属性而不是存储它:

from django.contrib.gis.measure import Distance, D
from geopy.distance import distance

@property
def distance(self):
    return Distance(m=distance(self.user_a.profile.location, self.user_b.profile.location).meters)

Geopy默认为Vincenty’s formulae,误差最高为0.5%,并且包含我将来会使用的许多其他功能。

以上内容返回一个GeoDjango距离对象,可以在测量之间轻松转换。

感谢您的帮助!

答案 1 :(得分:2)

  

如何使用GeoDjango计算此距离?   对于两个对象:

a.location.distance(b.location)

假设您有一个对象a是您的个人资料模型的一个实例,并且您希望找到每个其他个人资料的距离,您可以按照Geodjango reference中所述执行以下查询:

for profile in Profile.objects.distance(a.location):
    print profile.distance

如果您只想与距离不到1公里的物体进行比较:

for profile in Profile.objects.filter(location__dwithin=(a.location, D(km=1)).distance(a.location):
        print profile.distance
  

结果是什么单位?

单位可以是你想要的任何东西。返回的是距离物体。但是,默认值以米为单位,这就是上面的print语句将显示的内容。

  

是否有“最佳”方式存储此数据?浮动?小数?

最好的方法是不要保存它。通常,不会在数据库中保存可以通过简单查询计算的内容。记录数量将呈指数增长。例如,如果您的数据库中有N个配置文件,它将与N-1个其他配置文件具有一些距离属性。因此,您最终会在“缓存表”中找到N(N-1)条记录

答案 2 :(得分:0)

要在 GeoQuerySet 中计算距离,您可以将 annotatethe GeoDjango Distance database function 结合使用(不要与 the Distance measure 混淆)

from django.contrib.gis.db.models.functions import Distance

queryset = Profile.objects.annotate(
    distance=Distance('location', a.location)
)

注释距离将是 Distance measure。这意味着您可以执行以下操作:

for profile in queryset:
    print(profile.distance.mi)  # or km, etc

要过滤特定半径内的配置文件,您可以向 QuerySet 添加 filter

from django.contrib.gis.db.models.functions import Distance as DistanceDBFunction
from django.contrib.gis.measure import Distance as DistanceMeasure

queryset = Profile.objects.annotate(
    distance=DistanceDBFunction('location', a.location)
).filter(
    distance__lt=DistanceMeasure(mi=1)
)

如果您不需要带注释的距离,您可以简单地使用 the distance lookups

from django.contrib.gis.measure import Distance

queryset = Profile.objects.filter(
    location__distance_lt=(a.location, Distance(mi=1))
)

注意:自 Django 1.9 起,其他答案中提到的 Profile.objects.distance(a.location) 已被弃用。