Comments 15
Для решения проблемы большого количества запросов есть prefetch_related
0
Он тут не поможет. К тому же он тупее тупого.
Прямо сейчас в проекте:
Прямо сейчас в проекте:
FROM `socialaccount_socialaccount` WHERE `socialaccount_socialaccount`.`user_id` IN (40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40)
0
prefetch_related даст нехилую нагрузку на бд как по количеству запросов к бд так и по объему самих данных.
Работает он предельно просто: сначала выполняется основной запрос, а потом на уровне питон кода для всех RelatedObjects генерит новый запрос на выборку всех связанных объектов. В случае с моделью Page описанной в статье получается 5 запросов к бд. 1 на выборку самой Page и еще 4 на получение Translations для каждого переводимого поля. Теперь представим что в этих полям мы храним «оч.многобуквенные» данные для большого количества языков. Лично я бы предпочел множество запросов с меньшим объемом возвращаемых данных (может и зря)
Работает он предельно просто: сначала выполняется основной запрос, а потом на уровне питон кода для всех RelatedObjects генерит новый запрос на выборку всех связанных объектов. В случае с моделью Page описанной в статье получается 5 запросов к бд. 1 на выборку самой Page и еще 4 на получение Translations для каждого переводимого поля. Теперь представим что в этих полям мы храним «оч.многобуквенные» данные для большого количества языков. Лично я бы предпочел множество запросов с меньшим объемом возвращаемых данных (может и зря)
page.filed.translations.filter(lng='ru').first()
0
upd: ошибочка вышла в локальном примере. будет 9 запросов. 1 основной, 4 на получение id переводов и 4 на получение самих переводов.
было:
стало:
было:
Page.objects.filter(id=1).prefetch_related('content', 'title', 'description', 'keywords').first()
стало:
Page.objects.filter(id=1).prefetch_related('content__translations', 'title__translations', 'description__translations', 'keywords__translations').first()
, что равносильно 1му варианту только без отложенной разгузки.0
Боюсь Вы не правы. prefetch_related при не правильном использовании создаст только дополнительные проблемы. Когда мы говорим о фильтрации то он не кеширует запрос, который еще не был отфильтрован. Соответственно его нужно писать вместе с объектом Prefetch() и передавать в него уже отфильтрованный кверисет. это будет делать только 1 запрос в БД!
0
В общем-то, хорошее решение. Я про модель многоязычности :)
А сырой sql, на мой взгляд все равно лучше, хоть и менее DRY. Хранить его рядом с моделью и просить обновлять вместе с ней.
Ну не будете же вы каждую неделю переделывать таблицы? А if else в шесть слоев и map(lambda x) это уже что-то за гранью. ИМХО, конечно.
А сырой sql, на мой взгляд все равно лучше, хоть и менее DRY. Хранить его рядом с моделью и просить обновлять вместе с ней.
Ну не будете же вы каждую неделю переделывать таблицы? А if else в шесть слоев и map(lambda x) это уже что-то за гранью. ИМХО, конечно.
0
Дополню мысль: проще делать два запроса. Один для получения многоязычных полей и второй через орм (если понадобится), для получения всех остальных. Можно даже менеджер отдельный прикрутить.
0
Недостаток
raw
перед extra
— у него отсутсвуют стандартные методы, например filter
и get
.0
Это действительно так.
Но опять же, возвращаясь к модели: что там фильтровать?
И если это даже понадобится, лучше сделать дополнительный запрос с exists(). Т.е. я предлагаю использовать raw только чтобы стянуть переводы.
Но опять же, возвращаясь к модели: что там фильтровать?
И если это даже понадобится, лучше сделать дополнительный запрос с exists(). Т.е. я предлагаю использовать raw только чтобы стянуть переводы.
0
Навскидку — на странице вывести список дочерних страниц, причем title надо переводить.
0
Не вопрос:
В
children = parent.children.filter(is_active=True).order_by('order_field').values_list('id', flat=True)
pages = {x.id for x in Page.objects.extra(translations(where={'id': children}))}
ordered_pages = (pages[pk] for pk in children)
В
def translations
уже включить обработку where
на свой вкус.0
Кажется с ветки 1.6 поменялась сигнатура
join
. В ветке 1.5 не было параметра join_field
, а в tuple connection
передавалось 4 элемента0
Если вдруг кто-то все еще находит эту статью поиском по «Django left join», то могу сообщить, что это решение не работает уже как минимум для 1.8 версии. Сигнатура метода `join()` изменилась снова и теперь снова не принимает эти аргументы.
0
Sign up to leave a comment.
Django-orm в поисках LEFT JOIN