【发布时间】: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()
我会郑重声明这是一个人为的例子,但重点仍然是:
- 两个模型都没有外键关系(也不应该)
- 唯一的关系是通过距离
现在,我正在使用 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