我有两个Django模型(A和B),它们与任何外键都不相关,但都具有一个geometry字段。
class A(Model):
position = PointField(geography=True)
class B(Model):
position = PointField(geography=True)
我想在空间上关联它们,即给定A的查询集,能够获得B的查询集,其中包含与A的距离小于给定距离的那些记录。
我还没有找到使用纯Django ORM来做这种事情的方法。
当然,我可以在A中编写这样的属性:
@property
def nearby(self):
return B.objects.filter(position__dwithin=(self.position, 0.1))
但这只能让我在每个实例上获取附近的记录,而不能在单个查询中获取,这远没有效率。
我也尝试这样做:
nearby = B.objects.filter(position__dwithin=(OuterRef('position'), 0.1))
query = A.objects.annotate(nearby=Subquery(nearby.values('pk')))
list(query) # error here
但是,我在最后一行收到此错误:
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery
有人知道执行这种查询的更好方法(更有效)还是我的代码失败的原因?
非常感谢。
答案 0 :(得分:1)
我终于设法解决了这个问题,但最后我必须执行原始SQL查询。
这将返回带有注释的所有A记录,其中包括附近所有B记录的列表:
from collections import namedtuple
from django.db import connection
with connection.cursor() as cursor:
cursor.execute('''SELECT id, array_agg(b.id) as nearby FROM myapp_a a
LEFT JOIN myapp_b b ON ST_DWithin(a.position, p.position, 0.1)
GROUP BY a.id''')
nt_result = namedtuple('Result', [col[0] for col in cursor.description])
results = [nt_result(*row) for row in cursor.fetchall()]
参考文献: