Skip to main content
 首页 » 编程设计

python之相关模型上的 GeoDjango Distance() 注解

2024年08月15日42softidea

我有一个 Profile 类,它是一个带有 Location 模型的 OneToOne。每个配置文件都有一个且唯一的位置。

class Location(models.Model): 
    profile = models.OneToOne(Profile) 
    point = PointField() 

在我的一个 View 中,我显示了一个配置文件列表。例如,我首先查找具有位置的个人资料,然后查找关联的个人资料。

ref_location = Point(0,0) # point to calculate distances from 
locations = Location.objects.filter(point__distance_lte=(ref_location, D(m=50 * 1000))) \ 
profiles = Profile.objects.filter(pk__in=locations.values('profile_id')) 

我想要的是能够知道到每个配置文件实例的距离,例如我想做类似的事情:

profiles = Profile.objects.filter(pk__in=locations.values('profile_id'))\ 
.annotate(distance=Distance('location__point', ref_location)) 

然后遍历

for p in profiles: 
    print(p.distance.km) 

不可能

我能做的是 annotate locations,这没什么用,因为在模板中我遍历了 profiles,不是位置

请您参考如下方法:

您可以使用 Subquery (对于 Django 版本 >= 1.11)编写此查询:

locations = Location.objects.filter( 
    point__distance_lte=(OuterRef('ref_location'), D(m=50 * 1000)) 
).annotate(distance=Distance(OuterRef('point'), ref_location)) 
 
profiles = Profile.objects.filter( 
    pk__in=Subquery(locations.values('profile_id') 
).annotate(distance=Subquery(locations.values('distance'))) 

或者对于 Django 版本 < 1.11,您可以按如下方式编写此查询:

locations = Location.objects.filter( 
    point__distance_lte=(ref_location), D(m=50 * 1000)) 
).annotate(distance=Distance('point', ref_location)) 
 
profiles = Profile.objects.filter( 
    pk__in=locations.values('profile_id') 
).annotate(distance=locations.values('distance')) 

重点是您注释到 Location 对象的距离,然后将该距离注释到适当的配置文件。