Использование списочного понимания вместо цикла for при работе с Django QuerySets - PullRequest
2 голосов
/ 16 июля 2011

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

В настоящее время я работаю над функцией, которая должна перебирать словарь наборов запросов Django.Старый код использует оператор for-loop для итерации, и он работает нормально.Мой код, использующий понимание списка, возвращает наборы запросов django вместо объекта моей модели.

Вот код:

def get_children(parent):
  # The following works
  children = []
  for value in get_data_map(parent).itervalues():
    children += list(value)
  # This part doesn't work as intended.
  booms = [value for value in get_data_map(parent).itervalues() if value]
  import pdb
  pdb.set_trace()


(Pdb) type(children[0])
<class 'site.myapp.models.Children'>

(Pdb) type(booms[0])
<class 'django.db.models.query.QuerySet'>

Обратите внимание, что get_data_map возвращает словарь со значениями <class 'django.db.models.query.QuerySet'>

Эта часть кода является одной из самых трудоемких частей приложения.Если я получу эту работу над списком, можно надеяться, что скорость приложения вырастет в два раза.

Есть идеи, как мне ускорить эту часть кода?

Ответы [ 3 ]

5 голосов
/ 16 июля 2011

Ваша проблема не в for циклах и списках (лучше бы генераторы).Ваша проблема в слишком большом количестве запросов к базе данных .

Поскольку вы пытаетесь получить один список, вы должны пытаться получить его из одного запроса.Если бы вы объяснили, что было в вашем типичном QuerySet, мы могли бы показать вам, как лучше их объединить.Возможно использовать OR слияния на объектах Q.Или, может быть, создать набор целых чисел и передать его в фильтр __in=.

2 голосов
/ 16 июля 2011

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

a = [1,2,3]
b = [x for x in a if x ]

Вы ожидаете, что b также будет списком целых чисел, верно?Вы получаете список наборов запросов (лучше, чем список родителей), но вам все равно нужно присоединиться к ним.Вы можете сделать это, используя itertools.chain:

http://docs.python.org/library/itertools.html#itertools.chain

foos = itertools.chain(booms)

foos должно быть тем, что вы хотите.

1 голос
/ 04 февраля 2015

Согласитесь, сложно точно сказать, что происходит, но отладка проблем со скоростью django значительно упрощается благодаря панели инструментов отладки django:

https://github.com/django-debug-toolbar/django-debug-toolbar

Если проблема слишком многоdb hit, посмотрите вкладку «SQL-запросы» на панели инструментов, она покажет это очень четко.

...