django deliciouspie: получение дополнительных значений отношений m2m с использованием промежуточной модели

Я пытаюсь использовать Tastypie с отношениями ManyToMany, используя промежуточные модели (ключевое слово through) (https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships)

Я работаю с этими моделями:

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 баллов.

Я не смог найти никаких полезных ресурсов для повышения производительности. Я думал сделать собственный запрос с использованием метода .extra(), доступного для QuerySet, но ключевое слово JOIN недоступно (пару месяцев назад от патча отказались). И я не уверен, что подзапросы SELECT помогут.


person Solvik    schedule 17.07.2012    source источник


Ответы (1)


Рассматривали ли вы возможность изменить свой набор запросов для использования ресурса PointPosition? Судя по всему, то, что означает «точка» в вашей базе данных, на самом деле не совпадает с тем, что означает «точка» в вашем API, поэтому должен быть какой-то перевод, чтобы скрыть внутренние детали:

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

За счет необходимости настройки параметров фильтрации это избавит от необходимости выполнять более одного запроса. Ваш метод dehydrate может менять местами данные по мере необходимости. Вы также можете сэкономить некоторые накладные расходы, используя .values() для извлечения только необходимых полей в виде словаря, а не полных объектов.

person Chris Adams    schedule 18.07.2012
comment
Большое спасибо за ответ. На самом деле это то, что я сделал, но я не подумал использовать dehydrate для замены элементов, чтобы изменить порядок моего словаря. Классный совет :) - person Solvik; 19.07.2012
comment
Я потратил слишком много времени на борьбу с вкусняшками, прежде чем напомнил себе, что это всего лишь построение простой структуры данных, и не существует единственно правильного способа создания словаря. У меня есть по крайней мере один ресурс, в котором грубо переопределенный ModelResource стал простым ресурсом, который просто напрямую вызывает ORM для эффективного построения сложной структуры данных. - person Chris Adams; 19.07.2012