gpt4 book ai didi

python - 我如何通过距离加入两个不相关的 Django 模型?

转载 作者:行者123 更新时间:2023-11-28 19:24:05 25 4
gpt4 key购买 nike

我正在做一个 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”的解决方案来解决这个问题?

最佳答案

我建议使用 GraphQL/DataLoaders 来解决这个 N+1 问题,因为 DRF 不太适合它。但是,这可以在 DRF 中通过使用自定义 ListSerializer(django 在幕后自动为您创建一个)并重载两个 List/Child 序列化器的 to_representation 函数来完成:

class SchoolListSerializer(serializers.ListSerializer):
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
keys = [(item.id, item.location) for item in iterable]
# perform your bulk nearby query here using the id/locations
# the result should be a dict with school id keys and list of serialized hospital values
# {1: [hospital.to_dict(), hospital.to_dict(), ...], ...}
nearby_by_id = ...
extra = {
'nearby_hospitals_by_id': nearby_by_id
}
return [
self.child.to_representation(item, **extra) for item in iterable
]

class SchoolSerializer(serializers.ModelSerializer):

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

def to_representation(self, instance, **extra):
response = super().to_representation(instance)
response['nearby_hospitals'] = extra['nearby_hospitals_by_id'][instance.id]
return response

我省略了实际的数据库查询,但是该示例将适用于任何查询,无论数据位于何处。

关于python - 我如何通过距离加入两个不相关的 Django 模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17332441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com