我看到QuerySet
类有2种不同的方法似乎用于相同的目的(除非我弄错了):.__nonzero__
和.exists
。 (是的,我知道.__nonzero__
使用了bool
。)
我的问题:如果两种方法都检查查询集中是否有任何对象,为什么这两种方法有不同的实现?
Django文档说明了QuerySet.__nonzero__
:
注意:如果您要做的就是至少确定,请不要使用此项 存在一个结果,并且不需要实际的对象。它更多 有效使用exists()(见下文)。
(我在“下面”找不到任何有见地的东西。)
为什么QuerySet.__nonzero__
的实施效率不高?它是否试图实现与.exists
不同的东西? Django开发人员不做__nonzero__ = exists
的原因是什么?
答案 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.