GeoDjango:查找半径内的对象

GeoDjango: Finding objects in radius

我目前正在尝试获取包含在半径范围内的点的列表,但无法正常工作。到目前为止,这是我的视图代码:

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)

知道为什么它不起作用吗?谢谢

我在这里看到两个问题:

  1. 您没有在中心点指定 SRID,这意味着您正在比较两个不同的 SRID。您需要在 center_point:

    上设置 SRID
    center_point = 'SRID=4326;POINT(48.80033 2.49175)'
    
  2. 您的内联注释显示 POINT (2.49157 48.80029),但您的代码使用 POINT(48.80033 2.49175) - 请注意纬度和经度已互换位置。我不知道您打算使用其中的哪一个,但它们指的是完全不同的位置。

我相信您 运行 遇到了与此处描述的问题类似的问题:

首先我建议使用 dwithin instead of distance_lte for the filtering because it is optimized for that use (a very sort explanation )
我们从 dwithin 文档中读到:

Returns models where the distance to the geometry field from the lookup geometry are within the given distance from one another. Note that you can only provide Distance objects if the targeted geometries are in a projected system. For geographic geometries, you should use units of the geometry field (e.g. degrees for WGS84).

因此您必须将查询更改为如下内容:

meters_to_degrees = CONVERT YOUR METERS TO DEGREES
res = models.PointsResult.objects.filter(
    from_location__dwithin=(center_point, meters_to_degrees)
)

可以在此处找到米(特别是千米)到度的计算:How do I convert kilometres to degrees in Geodjango/GEOS?

最后一点,从 DRF 的角度来看,您正在 ViewSetlist 方法中创建模型实例。 那是绝对错误的,应该避免。 如果您想干扰对象创建过程,您应该覆盖 create 方法。