检查Django中的空查询集

Nik*_*las 156 django django-queryset

检查查询是否返回任何结果的推荐习惯用法是什么?
例:

orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
    # Do this with the results without querying again.
# Else, do something else...
Run Code Online (Sandbox Code Playgroud)

我想有几种不同的方法来检查这个,但我想知道一个有经验的Django用户会怎么做.文档中的大多数示例都忽略了没有找到任何内容的情况......

Leo*_*kov 178

从1.2版开始,Django就有了QuerySet.exists()方法效率最高:

if orgs.exists():
    # Do this...
else:
    # Do that...
Run Code Online (Sandbox Code Playgroud)

但是如果你要评估QuerySet,最好使用:

if orgs:
   ...
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请阅读QuerySet.exists()文档.


Ada*_*dam 173

if not orgs:
    # Do this...
else:
    # Do that...
Run Code Online (Sandbox Code Playgroud)

  • 这似乎也是文档中的首选,例如:https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#id7 (5认同)
  • 有关更详细的答案,请查看下面@leonid-shvechikov 的答案:如果不评估 qs,则使用 `.exists()` 会更有效。 (3认同)

Ada*_*ord 15

如果你有大量的对象,这可以(有时)更快:

try:
    orgs[0]
    # If you get here, it exists...
except IndexError:
    # Doesn't exist!
Run Code Online (Sandbox Code Playgroud)

在我正在使用一个庞大的数据库的项目上,not orgs是400+ ms,orgs.count()是250ms.在我最常见的用例(有结果的用例)中,这种技术通常可以达到20ms以下.(我发现一个案例,它是6.)

当然,可能要长得多,具体取决于数据库查找结果所需的距离.或者甚至更快,如果它快速找到一个; 因人而异.

编辑:这经常是慢orgs.count()如果结果是找不到的,特别是如果你筛选的条件是难得的一个; 因此,它在视图函数中特别有用,您需要确保视图存在或抛出Http404.(人们希望,在哪里,人们会要求提供经常存在的URL.)


小智 11

要检查查询集的空白:

if orgs.exists():
    # Do something
Run Code Online (Sandbox Code Playgroud)

或者您可以检查查询集中的第一个项目,如果它不存在,它将返回None:

if orgs.first():
    # Do something
Run Code Online (Sandbox Code Playgroud)

  • `if orgs.exists()`由[答案](http://stackoverflow.com/a/2373793/1906307)涵盖,该答案在此之前约5年提供.这个答案唯一能带给*表*的是*if orgs.first()`.(即使这是有争议的:它与大约5年前的`orgs [0]`[建议](http://stackoverflow.com/a/2098092/1906307)有很大不同吗?)你应该开发那部分答案:什么时候会想要这样做**而不是**之前提出的其他解决方案? (4认同)

Bar*_*osz 9

最有效的方式(在django 1.2之前)是这样的:

if orgs.count() == 0:
    # no results
else:
    # alrigh! let's continue...
Run Code Online (Sandbox Code Playgroud)

  • .exists()似乎更有效率 (5认同)
  • 除了在我的评论几个月后添加.exists(),并且Django 1.2(其中包含该API)在8个月之后发布.但要感谢投票,而不是费心去查看事实. (5认同)
  • 对不起,我在你的回答中添加了一些小编辑,以使其更加准确并得到积极评价. (4认同)

hed*_*oos 5

我不同意谓词

if not orgs:
Run Code Online (Sandbox Code Playgroud)

它应该是

if not orgs.count():
Run Code Online (Sandbox Code Playgroud)

我有一个相当大的结果集(约150k结果)的相同问题.操作符不会在QuerySet中重载,因此在进行检查之前,结果实际上是作为列表解压缩的.在我的情况下,执行时间减少了三个订单.

  • _\__非零_\_已在QuerySet中重载.如果结果未缓存(它永远不会首次使用查询集),_\_非零_ _ _的行为是迭代查询集中的所有元素.如果集合很大,这是非常糟糕的. (6认同)