2012-07-17 83 views
6

我試圖使用Tastypie使用中間模型(通過關鍵字)(https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationshipsDjango的tastypie:使用中間模型

多對多關係獲得一個M2M關係的額外價值有這些模特工作:

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')) 

我已經能夠獲取許多一對多的關係,但不是額外的領域 。這裏是我的tastypie代碼:

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子查詢是否會做到這一點。

回答

7

您是否考慮過將您的查詢集更改爲使用PointPosition資源?從它的聲音是什麼「點」是指在數據庫實際上不是與您的API中有什麼「點」是指這樣需要有一些翻譯隱藏內部細節:

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

在需要調整過濾參數的費用,這將避免需要執行多個查詢。您的dehydrate方法可以根據需要交換數據。您也可以通過使用.values()來節省一些開銷,只將必要的字段作爲字典提取出來,而不是完整的對象。

+0

非常感謝您的回答。 這實際上是我所做的,但我不認爲使用'脫水'交換元素重新排序我的字典。酷技巧:) – Solvik 2012-07-19 11:10:58

+1

我提醒自己,它只是建立一個簡單的數據結構,並沒有一個正確的方式來建立一本字典,我花了太多時間戰鬥tastypie。我至少有一個資源,其中粗糙的重寫ModelResource成爲一個簡單的資源,它只是直接調用ORM來有效地構建複雜的數據結構。 – 2012-07-19 13:37:39