Аннотирование записей Django с помощью объектов расстояния GeoDjango не работает

У меня есть таблица с GeoDjango GeometryField, и записи включают как точки, так и полигоны. Мне нужно вернуть те записи с геометрией Point в пределах заданного расстояния в км от заданной точки для внешнего API. Сначала я фильтрую записи с точками, аннотирую их объектом Distance, затем фильтрую по расстоянию.

Я обнаружил, что генерация набора запросов 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)

view

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 в своем комментарии. Есть две функции Distance в разных частях пакета django.contrib.gs. Количество аргументов для каждой из них разное, на что и указывает ошибка. django.contrib.gis.db.models.function.Distance здесь подходила функция annotate().

Вернуться на верх