Django:`QuerySet .__ nonzero__`和`QuerySet.exists`之间有什么区别?

时间:2013-01-16 21:30:30

标签: python django

我看到QuerySet类有2种不同的方法似乎用于相同的目的(除非我弄错了):.__nonzero__.exists。 (是的,我知道.__nonzero__使用了bool。)

我的问题:如果两种方法都检查查询集中是否有任何对象,为什么这两种方法有不同的实现?

Django文档说明了QuerySet.__nonzero__

  

注意:如果您要做的就是至少确定,请不要使用此项   存在一个结果,并且不需要实际的对象。它更多   有效使用exists()(见下文)。

(我在“下面”找不到任何有见地的东西。)

为什么QuerySet.__nonzero__的实施效率不高?它是否试图实现与.exists不同的东西? Django开发人员不做__nonzero__ = exists的原因是什么?

1 个答案:

答案 0 :(得分:8)

  

为什么QuerySet。非零的实施效率不高?它是否试图实现与.exists不同的东西? Django开发人员不做非零 =存在的原因是什么?

我认为这是因为exists仅在某些情况下才有效。

想象一下,如果__nonzero__具有“高效”实施,这种常见情况。

foos = Foo.objects.filter(bar='baz')

if foos:   # nonzero() calls exists() which causes extra query
           # even though the QS is already going to be evaluated
           # which in my projects is a common pattern. 
   print "Yay for foos!"
   for foo in foos:
       print foo

__nonzero__还会评估查询并将结果存储在缓存中。这意味着所有结果都存储在内存中。

exists只关心1行,甚至不实例化django对象,甚至不将其结果存储在缓存中。

如果您检查是否存在某些内容,并且不需要任何方式的数据,这似乎很有用。

  

为什么开发者不会__nonzero__ == exists

因为exists假设您不关心结果。如果__nonzero__调用exists,我们就没有结果。如果exists调用__nonzero__,我们会收集结果(可能很多),只是为了检查行是否存在。

示例:

bool( Foo.objects.filter(user=user) )  
# calls __nonzero__, evaluates, converts all fields to python objects 
# and stores in queryset._result_cache


Foo.objects.filter(user=user).exists()
# stores nothing, and query only returns one row.
# less data from DB and less python overhead generating django model instances.