【问题标题】:How might I join two unrelated Django models via distance?我如何通过距离加入两个不相关的 Django 模型?
【发布时间】:2013-06-24 07:44:17
【问题描述】:

我正在处理一个 Django 项目,该项目要求我通过 Web 服务为 School 表中的每个项目报告恰好在一定距离之外的所有医院。这是两个模型的虚拟实现:

class School(models.Model):
    location = models.PointField(srid=4326, geography=True)
    ...some other fields...
    objects = models.GeoManager()

class Hospital
    location = models.PointField(srid=4326, geography=True)
    ...some other fields...
    objects = models.GeoManager()

我会郑重声明这是一个人为的例子,但重点仍然是:

  1. 两个模型都没有外键关系(也不应该)
  2. 唯一的关系是通过距离

现在,我正在使用 Django Rest Framework (DRF) 来呈现我的请求,并且我正在使用它提供的 Serializer 类来执行以下操作:

class SchoolSerializer(serializers.ModelSerializer):

    nearby_hospitals = serializers.SerializerMethodField('get_nearby_hospitals')

    class Meta:
        model = School
        fields = ('location', 'nearby_hospitals',)

    def get_nearby_hospitals(self, obj):

        geom = obj.location

        try:

            locations = Hospitals.objects.filter(loc__dwithin=(geom, 10000))
            return HospitalSerializer(locations, many=True).data
        except:
            return

工作但它不是高效。本质上,DRF 会加载所有学校,然后从那里循环遍历每个学校并在 get_nearby_hospitals 中运行查询。数据库查询的数量等于 Schools 中的项目数加一(以获取 Schools)。

理想情况下,我想要一个 Django 解决方案,它可以执行以下操作(显然列出的字段、冲突 ID 列名的别名等):

SELECT * FROM schools JOIN 
hospitals ON ST_DWithin(schools.location, hospitals.location, 10000)

上述查询产生了适当距离内所有学校和医院的交集。我可以将这些结果与School.objects.all() 查询集手动合并,或者编写更好的查询并调用raw QuerySet 方法来一次性获得我想要的结果。

对于这个问题是否有更好或更多的“Django Way”解决方案?

【问题讨论】:

  • 你是怎么统计查询次数的?您使用的 Django Rest Framewok 视图是什么?
  • 我使用 Django Debug Toolbar 统计了查询的数量。有问题的视图是 DRF ListCreateAPIView。
  • 确保您测试的是页面的 json 版本,而不是 HTML。事实上,在 HTML 中为 Create API 视图构建表单可能会导致一堆通常不需要的查询。

标签: python django geospatial django-queryset geodjango


【解决方案1】:

我不确定它是否更好,但我认为你正在反方向解决问题。我看不出任何加入的理由。

class SchoolSerializer(serializers.ModelSerializer):

    nearby_hospitals = serializers.SerializerMethodField('get_nearby_hospitals')

    class Meta:
        model = School
        fields = ('location', 'nearby_hospitals',)

    def get_nearby_hospitals(self, obj):

        geom = obj.location

        try:
            # why do you query School model if you want nearby hospitals?
            locations = Hospital.objects.filter(location__distance_lte=(geom ,10000))
            return locations # not sure it's the good type to return though
        except:
            return

【讨论】:

  • 这是因为在我的示例中这是一个错字。正如您所说,“尝试”块下的行应该是医院。但是,它并没有解决这里的核心问题。
猜你喜欢
  • 1970-01-01
  • 2015-07-16
  • 2018-06-17
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多