Аннотирование записей 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().