2011-07-04 63 views
107

我想利用模型的最後10個實例,並有這樣的代碼:Django的 - 限制查詢結果

Model.objects.all().order_by('-id')[:10] 

這是真的,先拿起所有實例,然後只需要10最後的? 有沒有更有效的方法?

+4

https://docs.djangoproject.com/zh/dev/topics/db/queries/#limiting-querysets –

+0

沒錯。我錯過了這個地方。 – krzyhub

回答

184

Django查詢集很懶。這意味着只有當您明確詢問結果時,查詢纔會觸及數據庫。

因此,除非您打印或實際使用查詢結果,否則您可以進一步過濾而無需訪問數據庫。

正如你在下面看到的,你的代碼只執行一個sql查詢來只提取最後10個項目。

In [19]: import logging         
In [20]: l = logging.getLogger('django.db.backends')  
In [21]: l.setLevel(logging.DEBUG)      
In [22]: l.addHandler(logging.StreamHandler())  
In [23]: User.objects.all().order_by('-id')[:10]   
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=() 
Out[23]: [<User: hamdi>] 
22

其實我認爲LIMIT 10將發佈到數據庫,所以切片不會發生在Python中,但在數據庫中。

查看limiting-querysets瞭解更多信息。

-3

不,這是不正確的,正如文檔中明確解釋的那樣。

8

看起來像問題的解決方案不使用Django 1.7工作了,並引發錯誤: 「不能重新排序一旦切片已採取了查詢」

據迫使文檔https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets Python切片語法的「step」參數將評估Query。它的工作方式如下:

Model.objects.all().order_by('-id')[:10:1] 

我還在想,如果限制是在SQL或Python切片中執行的,則返回整個結果數組。將巨大的列表檢索到應用程序內存是沒有好處的。

+0

即使這個解決方案不適用於django> = 1.8測試。 –

-8

這不是實際發生的情況。 Django不會只提取所需的結果。 Django會加載完整的數據庫表(這是一個stup [id做的事情)並且只返回最後10條記錄。

我已通過在MySQL服務器上運行SHOW FULL PROCESSLIST來確認這一點,並且查詢沒有LIMIT子句。

如果您打算開發一個需要高可擴展性的大型應用程序,那麼Django不是一個好選擇。

+3

請提供更多詳細信息來證明這一點。評分最高的答案顯示,Django記錄爲正在運行的內容包含限制。我剛剛證實,Django 1.10仍然如此。我無法顯示完整的進程列表,因爲查詢太短而無法顯示。打開查詢日誌建議http://stackoverflow.com/questions/650238/how-to-show-the-last-queries-executed-on-mysql,MySql(或MariaDB具體)顯示該查詢包含限制條款。你有沒有做你的查詢,以便它可以被延遲加載? – Foon