2012-07-17 78 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