使用 GeoDjango Distance 对象注释 Django 记录失败

Annotating Django records with GeoDjango Distance objects fails

我有一个带有 GeoDjango GeometryField 的 table,记录包括点和多边形。对于外部 API,我需要 return 那些在距给定点以公里为单位的给定距离内具有点几何的记录。我首先过滤点记录,用距离对象注释那些记录,然后过滤距离。

我发现提供给序列化程序的 filtered 查询集的生成在我的 IDE 中运行良好。但是当我 运行 视图时,它挂在 annotate() 步骤上,并出现此错误:

File "/MyApp/api/views.py", line 102, in get
    qs1 = qs0.annotate(distance=Distance('geom', pnt))
TypeError: __init__() takes from 1 to 2 positional arguments but 3 were given

我想不通的是,为什么我可以逐步执行所有行来创建 qs2,如 qs.count() 和 qs2 排序结果所示,但是当我 运行该代码通过 URL,它在 annotate() 中断。

型号

from django.contrib.gis.db import models as geomodels

class PlaceGeom(models.Model):
    place = models.ForeignKey(Place,related_name='geoms')
    geom = geomodels.GeometryField(null=True, blank=True, srid=4326)

查看

from django.contrib.gis.geos import Polygon, Point
from django.contrib.gis.measure import D, Distance

class SpatialAPIView(generics.ListAPIView):
    def get(self, format=None, *args, **kwargs):
        params = self.request.query_params
    lon = params.get('lon', None)
    lat = params.get('lat', None)
    dist = params.get('km', None)
        
        pnt = Point(float(lon), float(lat), srid=4326)

        print(dist)
        >> 3

        qs0 = PlaceGeom.objects.extra(where=["geometrytype(geom) LIKE 'POINT'"])
        qs0.count()
        >> 1887148

        qs1 = qs0.annotate(distance=Distance('geom', pnt))
        qs2 = qs1.filter(geom__distance_lte=(pnt, D(km=dist))).order_by('distance')

        # results are sorted
        print(["{:.4f}".format(p.distance.km) for p in qs2][:5])
        >> ['0.0635', '0.1071', '0.1283', '0.4274', '1.0647']

        filtered = qs2[:pagesize] if pagesize and pagesize < 200 else qs2[:20]
        
        serial = PlaceSerializer
        serializer = serial(filtered, many=True, context={
            'request': self.request})
        serialized_data = serializer.data
        result = {
            "count": qs.count(),
            "type": "FeatureCollection",
            "features": serialized_data
        }
        return JsonResponse(result, safe=False, json_dumps_params={'ensure_ascii': False, 'indent': 2})

@iain-shelvington在他的评论中正确回答了这个问题。 django.contrib.gs 包的不同部分有两个 Distance 函数。正如错误指示的那样,每个参数的 # of arguments 都是不同的。 django.contrib.gis.db.models.function.Distance 适合此处的 annotate()。