django tastypie:使用中间模型获得m2m关系的额外值

Sol*_*vik 6 django many-to-many m2m tastypie

我正在尝试使用Tastypie与ManyToMany关系使用中间模型(通过关键字)(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'))
Run Code Online (Sandbox Code Playgroud)

我已经能够获取多对多关系,但不能获取额外的字段.这是我的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']
Run Code Online (Sandbox Code Playgroud)

我一直在尝试使用一种方法来水合我的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 
Run Code Online (Sandbox Code Playgroud)

但问题在于它创建的查询数量与我有的数量相同:当你有+8000点时,它是一个真正的性能杀手.

我无法找到任何有用的资源来获得性能.我正在考虑使用可用于QuerySet的.extra()方法进行自定义查询,但JOIN关键字不可用(几个月前该修补程序已被拒绝).而且我不确定SELECT子查询是否可以解决问题.

Chr*_*ams 7

您是否考虑过更改查询集以使用该PointPosition资源?从它的声音中,"Point"在数据库中的含义实际上与"Point"在API中的含义不同,因此需要进行一些翻译以隐藏内部细节:

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

以需要调整过滤参数为代价,这将避免需要执行多个查询.您的dehydrate方法可以根据需要交换数据.您还可以通过.values()仅将必要字段作为字典而不是完整对象拉出来节省一些开销.