6

中間モデルを使用して(キーワードを介して)多対多の関係でTastypieを使用しようとしています( https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many -関係

私はこれらのモデルで作業しています:

class Point(models.Model):
    ...
    value = models.FloatField(_('Value'), null=True)
    rooms = models.ManyToManyField('rooms.Room', through='points.PointPosition')

class Room(models.Model):
    title = models.CharField(max_length=64)

class PointPosition(models.Model):
    point = models.ForeignKey('points.Point', verbose_name=_('Point'))
    room = models.ForeignKey('rooms.Room', verbose_name=_('Room'))
    x = models.IntegerField(_('Y'))
    y = models.IntegerField(_('X'))

多対多の関係を取得することはできましたが、余分なフィールドを取得することはできませんでした。これが私のおいしいコードです:

class PointResource(ModelResource):
    class Meta:
        queryset = Point.objects.select_related(
            depth=10
            ).prefetch_related('rooms').all()
        resource_name = 'point'
        allowed_methods = ['get']

    ...
    value = fields.FloatField()
    rooms = fields.ToManyField('rooms.api.RoomResource', 'rooms', full=True)

class RoomResource(ModelResource):
    class Meta:
        queryset = Room.objects.all()
        resource_name = 'room'
        allowed_methods = ['get']

私は次のように、 PointResourceの部屋変数をハイドレイトするメソッドを使用しようとしています。

def dehydrate_rooms(self, bundle):                                                                                                                                                                                                                          
    rooms = []                                                                                                                                                                                                                                              
    for room in bundle.obj.rooms.all():                                                                                                                                                                                                                     
        position = PointPosition.objects.get(                                                                                                                                                                                                               
            room_id = room.pk,                                                                                                                                                                                                                              
            point_id = bundle.obj.pk)                                                                                                                                                                                                                                               
        rooms.append({'id': room.pk,                                                                                                                                                                                                                                 
             'title': room.title,                                                                                                                                                                                                                           
             'x': position.x,                                                                                                                                                                                                                               
             'y': position.y})                                                                                                                                                                                                                                               
    return rooms 

しかし、問題は、私がポイントを持っているのと同じ数のクエリを作成することです。+ 8000ポイントを持っていると、パフォーマンスが大幅に低下します。

パフォーマンスを上げるために役立つリソースを見つけることができませんでした。QuerySetで使用可能な.extra()メソッドを使用してカスタムクエリを実行することを考えていましたが、JOINキーワードを使用できません(パッチは数か月前に拒否されました)。そして、SELECTサブクエリがうまくいくかどうかはわかりません。

4

1 に答える 1

7

PointPositionリソースを使用するようにクエリセットを変更することを検討しましたか? その音から、データベースでの「ポイント」の意味は、API での「ポイント」の意味と実際には同じではないため、内部の詳細を隠すために何らかの変換が必要です。

class PointResource(ModelResource):
    class Meta:
        queryset = PointPosition.objects.select_related("point", "room")
        resource_name = 'point'
        allowed_methods = ('get', )

フィルタリング パラメータを調整する必要がありますが、これにより、複数のクエリを実行する必要がなくなります。メソッドdehydrateは、必要に応じてデータを交換できます。.values()完全なオブジェクトではなく、必要なフィールドのみをディクショナリとして引き出すことで、オーバーヘッドを節約することもできます。

于 2012-07-18T20:00:27.050 に答える