GeoDjango:在半径范围内查找对象

4

我目前正在尝试获取一个半径内的点列表,但是我无法让它正常工作。以下是我目前视图的代码:

from django.contrib.gis.geos import Point
from django.contrib.gis.measure import Distance

class AreaInfoViewSet(viewsets.ViewSet):
    queryset = models.AreaInfoRequest.objects.all()
    serializer_class = serializers.AreaInfoRequestRequestSerializer

    def list(self, request):
        center_point = 'POINT(48.80033 2.49175)'
        radius = "50.0"

        data = {"center_point": center_point, "radius": radius, "source_ip": utils.get_client_ip(request)}
        serializer = serializers.AreaInfoRequestRequestSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # Contains an object with field "from_location"="SRID=4326;POINT (48.80029 2.49157)"
        objs = models.PointsResult.objects.all()

        float_radius = serializer.data["radius"]
        center_point = serializer.data["center_point"] # Point object

        res = models.PointsResult.objects.filter(from_location__distance_lte=(
            center_point, Distance({"meter": float_radius})))
        # Here the res doesn't contain the unique object in the db even if it's within the radius

        return Response(res)

有什么想法为什么它不起作用吗?谢谢。
2个回答

2

I can see two issues here:

  1. You haven't specified the SRID on your center point, which means you're comparing two different SRIDs. You need to set the SRID on center_point:

    center_point = 'SRID=4326;POINT(48.80033 2.49175)'
    
  2. Your inline comment says POINT (2.49157 48.80029), but your code uses POINT(48.80033 2.49175) - note that the latitude and longitude have swapped places. I don't know which of these you intend to use, but they refer to quite different locations.


抱歉,我在实验中交换了这两个。实际上,它们并没有被交换。我编辑了我的问题并解决了这个问题。 - E-Kami
即使使用 center_point = 'SRID=4326;POINT(48.80033 2.49175)' 也不起作用,我相信默认情况下所有我创建的 Point 对象都使用 SRID=4326 - E-Kami
请提供您期望匹配的点的样本数据? - solarissmoke
应该找到注释中包含一个带有字段"from_location" = "SRID = 4326; POINT(48.80029 2.49157)"的对象:objs = models.PointsResult.objects.all() - E-Kami

2
我相信您遇到了一个类似于此处描述的问题:GeoDjango&SpatiaLite——过滤附近的对象
首先,我建议使用dwithin而不是distance_lte来进行过滤,因为它针对该用途进行了优化(这里有一个非常简短的解释)。 从文档中,我们可以读到:

返回距离查找几何图形的距离在给定距离内的模型。 请注意,如果目标几何图形处于投影系统中,则只能提供Distance对象。对于地理几何图形,您应该使用几何字段的单位(例如WGS84的度数)。

因此,您必须将查询更改为以下内容:
meters_to_degrees = CONVERT YOUR METERS TO DEGREES
res = models.PointsResult.objects.filter(
    from_location__dwithin=(center_point, meters_to_degrees)
)

一种将米(特别是千米)转换为度数的计算方法可以在此处找到:
如何在Geodjango / GEOS中将千米转换为度? 最后,从DRF的角度来看,您正在ViewSetlist方法中创建模型实例。那是绝对错误的,应该避免。如果您想干预对象创建过程,应该重写create方法。

1
非常感谢您的回复!我认为这就是我正在寻找的,很快就会尝试。此外,感谢 DRF 的建议,我将把这个视图更改为 APIView 并使用“get”。 - E-Kami
@E-Kami 很高兴能帮助 :) - John Moutafis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接