Rrooom
@Rrooom

Как избавитсья от лишних запросов в Django?

В Django использую raw-запрос, довольно прямолинейно:
object_list = MyModel.objects.raw(...)

С этим появляется две проблемы.
Первая - еще во вьюхе считаются агрегированные данные в цикле:
for each in object_list:
    total[...] += each.x
    total[...] += each.x

Ну а затем, еще раз, по данным пробегаются в цикле уже в шаблоне. И джанго почему-то не кэширует результат - а выполняется запрос еще раз.

Вторая проблема. В шаблоне, при выводе результатов джанго автоматически обращается к другой модели, связанной ForeignKey. Причем, для каждого объекта он выполняет запрос - сотни запросов, тупо для того, что бы забрать имя категории!

Как с этим бороться?
  • Вопрос задан
  • 2631 просмотр
Пригласить эксперта
Ответы на вопрос 3
ur001
@ur001
Программист. Искатель. Сноб. Социальный ассоциатор
Почти на всех больших проектах мне удавалось избегать использования .raw(), по этому я спросил вас, что там внутри. Почти наверняка есть обходные пути.

Для того, чтобы быть уверенным, что запрос не будет выполнен несколько раз, его можно сразу превратить в список:

object_list = list(MyModel.objects.raw(...))

Для выполнения prefetch_related в raw запросах обычно используют prefetch_related_objects, хотя эта функция в Django не документирована:

from django.db.models.query import prefetch_related_objects
object_list = list(MyModel.objects.raw(...))
prefetch_related_objects(raw_qs, ['fk_field', 'another_fk_field', ...])


Для изучения когда и какие запросы выполняются удобно пользоваться консолью debugsqlshell из django debug toolbar (которую вы скорее всего используете).
Ответ написан
Комментировать
inlanger
@inlanger
Django программист
Или сами прикрутите сами кеширование, или смиритесь. Для Django это нормально.
Ответ написан
Комментировать
alternativshik
@alternativshik
По поводу последнего - prefetch_related вам поможет.
По поводу первого - в том же цикле просто сделайте другой лист с данными из данных object_list и джанга не будет делать запрос 2 раз.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы