2009-09-07 101 views
104

檢查查詢是否返回任何結果的推薦方法是什麼?
例子:檢查Django中的空查詢集

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

我想有這個檢查的幾種不同的方式,但我想知道有經驗的Django的用戶會怎麼做。 在文檔中的大多數例子只是忽略這裏什麼也沒有找到的情況下...

回答

101
if not orgs: 
    # Do this... 
else: 
    # Do that... 
+3

這似乎在文檔中也是首選,例如:https:// docs。djangoproject.com/en/1.8/topics/http/shortcuts/#id7 – Wtower 2015-05-22 09:02:08

+0

@Wtower如果過濾表達式沒有命中任何記錄或產生結果的「列表」,那麼您引用的代碼已經爲合同提高了404有記錄。那裏的代碼只會碰到一次數據庫。如果他們使用'exist()'或者'count()'來檢查是否有記錄返回,那麼他們會敲擊數據庫兩次(一次檢查,一次獲取記錄)。這是一個特定的情況。它不包含在*一般情況下*,知道一個查詢是否會返回記錄的首選方法是使用do'if queryset:...' – Louis 2015-11-03 16:26:22

+1

@Louis我引用的代碼只是它包含的一個示例一行'if not my_objects:'來證明他們是如何在文檔中執行的。所有其他都完全不相關,所以我不明白你的觀點。他們也可以提出一千個問題,這仍然是完全不相關的,因爲這不是這個答案的重點,我明確表示我同意。 – Wtower 2015-11-04 08:47:13

3

最有效的方法(Django的前1.2)是這樣的:

if orgs.count() == 0: 
    # no results 
else: 
    # alrigh! let's continue... 
+3

.exists()似乎更有效率 – dzida 2012-03-28 07:12:15

+3

除了.exists()在我的評論幾個月後被添加,Django 1.2(包含該API)在8個月後發佈。但感謝您的低投票率,並且不打擾檢查事實。 – Bartosz 2012-09-12 20:26:22

+4

對不起,我在答案中添加了小編輯,使其更加準確,並且投票結果爲正面。 – dzida 2012-09-13 10:10:41

14

如果你有一個龐大的數字對象,這可以(有時)要快得多:

try: 
    orgs[0] 
    # If you get here, it exists... 
except IndexError: 
    # Doesn't exist! 

在一個項目中,我正在與一個龐大的數據庫,not orgs是400個+ MS和orgs.count()是25 0毫秒。在我最常見的使用情況下(有結果的情況),這種技術通常可以將這種情況降低到20毫秒以下。 (我發現有一個案例,它是6.)

可能會更長,當然,取決於數據庫有多遠才能找到結果。甚至更快,如果它發現一個很快;因人而異。

編輯:這往往會比orgs.count()慢,如果沒有找到結果,特別是如果你過濾的條件是罕見的;因此,在需要確保視圖存在或拋出Http404的視圖函數中,它尤其有用。 (其中,人們希望人們要求的URL經常存在)

134

從1.2版本開始,Django就有了QuerySet。 exists()方法,該方法是最有效的:

if orgs.exists(): 
    # Do this... 
else: 
    # Do that... 

但是,如果你要評估的QuerySet無論如何,它是更好地使用:

if orgs: 
    ... 

欲瞭解更多信息read QuerySet.exists() documentation

5

我與謂詞

if not orgs: 

不同意它應該是

if not orgs.count(): 

我是有一個相當大的結果集(〜150K結果)相同的問題。運算符在QuerySet中不會被重載,因此在檢查之前結果實際上是作爲列表解壓縮的。在我的情況下,執行時間減少了三個命令。

+4

_ \ _非零_ _已在QuerySet中重載。如果結果沒有被緩存(它從來不是第一次使用queryset),_ \ _非零_ \ _的行爲是迭代queryset中的所有元素。如果集合很大,這是非常糟糕的。 – hedleyroos 2011-07-30 15:45:22

9

要檢查查詢集的空虛:

if orgs.exists(): 
    # Do something 

,或者你可以在一個查詢集檢查的第一個項目,如果它不存在,它會返回None

if orgs.first(): 
    # Do something 
+1

'如果orgs.exists()'覆蓋了大約5年前提供的[答案](http://stackoverflow.com/a/2373793/1906307)。這個答案帶來的唯一的事情就是org.first()'。 (即使這是有爭議的:大約5年前與做orgs [0]'[建議](http://stackoverflow.com/a/2098092/1906307)有很大區別嗎?)你應該開發那部分答案是:什麼時候想要這樣做而不是**早先提出的其他解決方案? – Louis 2015-11-03 16:33:22