GeoDjango GeoQuerySet.distance() 在指定反向关系字段时出现 'ST_Distance output only available on GeometryFields

2 投票
1 回答
831 浏览
提问于 2025-04-18 15:25

根据文档和其他问题,按距离对GeoQuerySet进行排序应该很简单,但我在实现时遇到了麻烦。下面是一个例子,来展示我遇到的问题:

假设我在两个不同的应用中有两个模型。一个模型在appA,另一个在appB,定义如下:

# appA/models.py
class Store(models.Model):
        title = models.CharField()


# appB/models.py
from appA.models import Store

class StoreLocation(models.Model):
    store = models.ForiegnKey(Store)
    location = models.PointField()

现在,我想获取所有距离用户位置(user_location)两英里以内的Stores,像这样:

stores = Store.objects.filter(storelocation__location__dwithin(user_location, D(mi=2))

到这里为止,一切正常。问题出现在我想按距离对Stores进行排序时,距离用户位置的距离:

stores = Store.objects.filter(storelocation__location__dwithin(user_location, D(mi=2))\
         .distance(user_loc, field_name='storelocation__location')\
         .order_by('distance')

这导致了一个错误:TypeError: ST_Distance output only available on GeometryFields

StoreLocation模型的location字段是PointField,这是一种GeometryField。所以问题出在通过field_name='storelocation__location'进行的反向关系查找上。

有一个Django的支持请求(https://code.djangoproject.com/ticket/22352),请求支持在field_name中进行OneToOne关系的反向关系查找,但我的模型是通过ForeignKey建立的OneToMany关系,所以我不确定这个支持请求是否适用于我的问题。

根据Django的文档(https://docs.djangoproject.com/en/1.6/ref/contrib/gis/geoquerysets/#geoqueryset-methods),看起来我并没有错误使用任何东西。

在GeoQuerySet方法的field_name参数中,是否允许进行反向关系查找?还是我只是做错了什么?

这个问题中提供的解决方案(GeoDjango distance query for a ForeignKey Relationship)也没有帮助。

1 个回答

1

我怀疑你遇到的问题跟Django的支持票22352里提到的情况差不多,因为相关字段(无论是一对一还是一对多)使用了很多相同的代码。

不过,你仍然可以高效地获取按距离排序的附近商店:

locations = StoreLocation.objects.filter(location__dwithin=(user_location, D(mi=2)))
locations = locations.distance(user_location).order_by('distance')
stores = [sl.store for sl in locations.select_related('store')]

但是,这样做就失去了将stores作为查询集的好处(查询集可以进一步过滤、切片等等)。

撰写回答