GeoDjango根据模型字段距离过滤

7
我的问题与这个问题几乎相同。但它很旧,感觉这应该是一个非常普遍的情况,可能有更好的解决方案。
我的模型大致如下:
class Person(models.Model):
    location = models.PointField(srid=4326)
    willing_to_travel = models.IntegerField()

如果我想要找到距离点 p 一定距离(比如10英里)内的所有人,可以按照以下方式进行:

Person.objects.filter(location__distance_lte=(p, D(mi=10)))

我想获取所有在特定位置附近的willing_to_travel距离内的人员实例。

1个回答

4
这得益于Django 1.9中引入的地理数据库函数,它允许用户在Django中使用地理数据库函数进行注释、聚合或过滤。最吸引我们的是Distance,您可以按照以下方式将其应用到您的情况中:
from django.contrib.gis.db.models.functions import Distance
from django.db.models import F
Person.objects.annotate(distance=Distance('location', p)
       ).filter(distance__lte=F('willing_to_travel'))

请注意,这里有微妙的差别,我们没有直接使用 distance_lte,而是创建了一个注释,生成了一个距离列。然后我们在模型查询集上使用标准的 __lt 比较符号。大致翻译成:
   ... WHERE ST_Distance(app_person.location, ST_GeogFromWKB(...)) < 
       app_person.willing_to_travel

这个函数类似于 distance_lte,它可以完成任务,不过效率没有使用 ST_Dwithin 高。

由于此查询是基于“字段单位”(即度数)来操作的,所以需要将位置转换为地理坐标。如果使用地理字段,则距离将用米来表示。


在我阅读的所有类似问题中,这个问题有正确的“from django.contrib.gis.db.models.functions import Distance”注释。 - mjabadilla
Person.objects.annotate(distance=Distance('location', p) 中的 p 是什么? - Harry Moreno
那么 django.contrib.gis.geos.Point 对象呢? - Harry Moreno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接