我的Profile
模型有这个字段:
location = models.PointField(geography=True, dim=2, srid=4326)
我想使用GeoDjango计算这两个locations
之间的距离(考虑到地球是一个椭球体),这样我就可以将这个距离存储在数据库中。
我已经回顾过以前的类似问题,并且没有发现它们有用。没有答案可以解释发生了什么或者它为什么会起作用。
我使用Django 1.8和GeoDjango所需的最新版本库。
谢谢!
答案 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
中计算距离,您可以将 annotate
与 the 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)
已被弃用。