Эффективная нумерация страниц от Join в Django

У меня проблема с объединением и разбиением на страницы. У меня есть 3 модели:

  • Подушечка
  • Ярлык
  • ТегОтношение

Я использую отношение Tag для управления отношением ManyToMany между контактными площадками и тегами (с атрибутом through поля ManyToMany). Теперь, когда я выполняю объединение таблиц Pad и Tag, это дает мне что-то вроде этого...

pad.name   tag.name     etc
---------------------------
pad1       tag1         ...
pad1       tag2         ...
pad2       tag3         ...

Теперь, когда я создаю объект Paginator() из этих результатов, это, очевидно, неправильное количество элементов на странице. Мне пришлось бы перебирать ВСЕ результаты и создавать такой словарь...

[{name:'pad1', tags:['tag1', 'tag2']}, {name:'pad2' ....]

... и используйте для этого Paginator, чтобы получить правильные страницы.

Каков наилучший подход к этой проблеме? Я мог бы сделать запрос к БД для каждого объекта Pad на текущей странице, чтобы получить его теги, но я думаю, что это рано или поздно убьет сервер (должно быть производительным).

Содержание результатов также может быть довольно длинным, и повторение всего набора потребует много системной памяти (или это будет? Просветите меня :)).


person Erik Aigner    schedule 07.12.2009    source источник


Ответы (1)


Если я правильно понимаю, вы должны разбивать страницы на Pad.objects.all(), а затем использовать select_related в объектах TagRelation в обоих случаях для получения соответствующих тегов всего за один (дополнительный) запрос и использования этих данных в вашем представлении/шаблоне. Что-то типа:

thispagepadids = [o.id for o in mypageobject.object_list]
tagrels = TagRelation.objects.filter(pad__id__in=thispagetagids).select_related('tag','pad'))

(при условии, что у вас есть объект страницы в mypageobject). Затем вы можете получить площадку и тег для любого заданного tagrel в коде (используя regroup тег шаблона, вероятно, самый простой способ сделать это), но БД выполняет только один (гигантский) запрос, и ваш счетчик разбиения на страницы по-прежнему правильный.

Обратите внимание, что нам пришлось выполнить 2 запроса, потому что вы не можете просто использовать select_related непосредственно в поле «многие ко многим» (см. этот билет), но вы можете использовать его, чтобы следовать FK в обоих направлениях из промежуточной таблицы m2m.

person Yoni Samlan    schedule 07.12.2009
comment
к сожалению, это не позволяет мне также фильтровать записи по тегу. кажется, нет никакого способа обойти гигантское объединение и ручную (в коде) постобработку. - person Erik Aigner; 08.12.2009
comment
Ах, но если вы хотите отфильтровать по тегу (при условии, что вы говорите только об одном конкретном теге), вы можете безопасно снова разбить TagRelation на страницы, и только это: TagRelation.objects.filter(tag=someTagObject), поскольку ваш объект разбиения на страницы должен дать вам ровно один тагрел для каждого пэда (при условии, что вы не можете пометить пэд одним и тем же тегом несколько раз). - person Yoni Samlan; 09.12.2009