2011-07-16 27 views
2

我试图调整在速度部受苦的应用程序。因此,我已经开始将所有的for-loop语句转换为列表解析。在使用Django查询集时使用列表理解而不是循环

目前,我正在研究一个需要遍历Django查询集字典的函数。旧代码使用for-loop语句来遍历这个,它工作正常。我使用list comprehension的代码返回的是django querysets,而不是我的模型对象。

下面是代码:

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'>

的这部分代码的消费应用程序的一部分时间最多的一个。如果我在列表解析中得到这个工作,应用程序的速度将有望提高两倍。

任何想法如何加快这部分代码?

+1

是什么让你认为列表推导比在'...循环中进行常规'for ...更快? – dcrosta

+1

我已经做了一个关于生成器,列表解析,循环和映射的简单测试,并且列表解析比..循环快两倍。 – mohi666

回答

5

你的问题不是for循环与列表解析(更好的是生成器)。你的问题是太多查询到数据库

由于您试图获得一个列表,您应该尝试从一个查询中获取它。如果您解释了典型QuerySet中的内容,我们可以向您展示如何最好地合并它们。也许在Q对象上使用OR合并。或者可能构建一组整数并将其提供给__in=过滤器。

+0

假设这是不可解的,并且OP实际上并未使用整个列表,itertools.chain会使其更快,因为并不是每个查询集都会导致查询(因为懒惰评估)。 – markijbema

+0

是的,在给出这么少的信息的时候很难说出要做什么。但是,我仍然发现查询开销比Django中的循环开销要大得多。 –

2

您的解决方案不起作用,因为您正在创建查询集列表。每个值都是一个查询集,并且您无法将其加入。比较:

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

同意这很难说这是怎么回事准确,但是在调试Django的速度问题是由极大地更容易使用的Django调试工具栏:

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

如果问题实在是太多了分贝命中,观看工具栏上的“SQL查询”选项卡将显示非常清楚。