4

私は Django プロジェクトに取り組んでおり、School テーブルの各アイテムについて、たまたま一定の距離にあるすべての病院を Web サービス経由で報告する必要があります。以下は、2 つのモデルのダミーの実装です。

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) を使用してリクエストをレンダリングしており、Django Rest Framework (DRF) が提供するシリアライザー クラスを使用して、次の行に沿って何かを実行しています。

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 内のアイテムの数に 1 を加えた数 (Schools を取得するため) に等しくなります。

理想的には、これらの行に沿って何かを実行する Django ソリューションが必要です (明らかに、リストされているフィールド、ID 列名を衝突させるためのエイリアスなど):

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

上記のクエリは、適切な距離内にあるすべての学校と病院の交差点を生成します。これらの結果を手動でクエリセットにマージするか、より良いクエリを作成してQuerySet メソッドをSchool.objects.all()呼び出して、求めているものを 1 回で取得することができます。raw

この問題に対するより良い、またはより多くの「Django Way」ソリューションはありますか?

4

2 に答える 2

-1

それが良いかどうかはわかりませんが、問題を逆方向に進めていると思います。JOIN の理由はまったくありません。

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
于 2013-06-27T00:44:15.710 に答える