Django框架 querySet功能解析

2022-10-04 16:15:12 字數 3273 閱讀 3254

可切片

使用python 的切片語法來限制查詢集記錄的數目 。它等同於sql 的limit 和offset 子句。

>>> entry.objects.all()[:5] # (limit 5)

entry.objects.all()[5:10] # (offset 5 limit 5)

不支援負的索引(例如entry.objects.all()[-1])。通常,查詢集 的切片返回乙個新的查詢集 —— 它不會執行查詢。   

可迭代articlelist=models.article.objects.all()

for article in articlelist:

print(article.title)

惰性查詢

查詢集 是惰性執行的 —— 建立查詢集不會帶來任何資料庫的訪問。你可以將過濾器保持一整天,直到查詢集 需要求值時,django 才會真正執行這個查詢。

queryresult=models.article.objects.all() # not hits database

print(queryresult) # hits database

for article in queryresult:

print(article.title) # hits database

一般來說,只有在「請求」查詢集 的結果時才會到資料庫中去獲取它們。當你確實需要結果時,查詢集 通過訪問資料庫來求值。 關於求值發生的準確時間,參見何時計算查詢集。  

快取機制

每個查詢集都包含乙個快取來最小化對資料庫的訪問。理解它是如何工作的將讓你編寫最高效的**。

在乙個新建立的查詢集中,快取為空。首次對查詢集進行求值 —— 同時發生資料庫查詢 ——django 將儲存查詢的結khwpe果到查詢集的快取中並返回明確請求的結果(例如,如果正在迭代查詢集,則返回下乙個結果)。接下來對該查詢集 的求值將重用快取的結果。

請牢記這個快取行為,因為對查詢集使用不當的話,它會坑你的。例如,下面的語句建立兩個查詢集,對它們求值,然後扔掉它們:

print([a.title for a in models.article.objects.all()])

print([a.create_time fowww.cppcns.comr a in models.article.objects.all()])

這意味著相同的資料庫查詢將執行兩次,顯然倍增了你的資料庫負載。同時,還有可能兩個結果列表並不包含相同的資料庫記錄,因為在兩次請求期間有可能有article被新增進來或刪除掉。為了避免這個問題,只需儲存查詢集並重新使用它: 

queryresult=models.article.objects.all()

print([a.title for a in queryresult])

print([a.create_time for a in queryresult])

何時查詢集不會被快取?

查詢集不會永遠快取它們的結果。當只對查詢集的部分進行求值時會檢查快取, 如果這個部分不在快取中,那麼接下來查詢返回的記錄都將不會被快取。所以,這意味著使用切片或索引來限制查詢集將不會填充快取。

例如,重複獲取查詢集物件中乙個特定的索引將每次都查詢資料庫:

>>> queryset = entry.objects.all()

>>> print queryset[5] # queries the database

>>> print queryset[5] # queries the database again

然而,如果已經對全部查詢集求值過,則將檢查快取:  

>>> queryset = entry.objects.all()

>>> [entry for entry in queryset] # queries the database

khwpe>>> print queryset[5] # uses cache

>>> print queryset[5] # uses cache

下面是一些其它例子,它們會使得全部的查詢集被求值並填充到快取中:

>>> [entry for entry in quer

>>> bool(queryset)

>>> entry in queryset

>>> list(queryset)

注:簡單地列印查詢集不會填充快取。  

queryresult=models.article.objects.all()

print(queryresult) # hits database

print(queryresult) # hits database

exists()與iterator()方法

exists:

簡單的使用if語句進行判斷也會完全執行整個queryset並且把資料放入cachwww.cppcns.come,雖然你並不需要這些 資料!為了避免這個,可以用exists()方法來檢查是否有資料:

if queryresult.exists():

#select (1) as "a" from "blog_article" limit 1; args=()

print("exists...")

iterator:

當queryset非常巨大時,cache會成為問題。

處理成千上萬的記錄時,將它們一次裝入記憶體是很浪費的。更糟糕的是,巨大的queryset可能會鎖住系統 程序,讓你的程式瀕臨崩潰。要避免在遍歷資料的同時產生queryset cache,可以使用iterator()方法 來獲取資料,處理完資料就將其丟棄。

objs = book.objects.all().iterator()

# iterator()可以一次只從資料庫獲取少量資料,這樣可以節省記憶體

for obj in objs:

print(obj.title)

#but,再次遍歷沒有列印,因為迭代器已經在上一次遍歷(next)到最後一次了,沒得遍歷了

for obj in objs:

print(obj.title)

當然,使用iterator()方法來防止生成cache,意味著遍歷同乙個queryset時會重複執行查詢。所以使 #用iterator()的時候要當心,確保你的**在操作乙個大的queryset時沒有重複執行查詢。

總結:queryset的cache是用於減少程式對資料庫的查詢,在通常的使用下會保證只有在需要的時候才會查詢資料庫。 使用exists()和iterator()方法可以優化程式對記憶體的使用。不過,由於它們並不會生成queryset cache,可能 會造成額外的資料庫查詢。 

本文標題: django框架 queryset功能解析

本文位址:

Django 框架 Django介紹

django 使用 python 語言寫的開源 web 開發框架,並遵循 mvc 設計。勞倫斯出版集團為了開發以新聞內容為主的 而開發出來了這個框架。django 今年來應用越來越廣泛。django 的主要目的是簡便 快速的開發資料庫驅動的 它強調 復用,多個元件可以很方便的以 外掛程式 形式服務於...

初試django框架

安裝django 當前安裝的版本是1.10.5 pip install django 新建乙個名為mysite的專案 django admin.py startproject mysite 進入mysite目錄,結構如下 mysite manage.py mysite settings.py url...

django框架基礎

djang 是用python 語言寫的開源 web開發框架,並遵循 mvc設計 並且django 有乙個專有名詞 mvtm 全拼為model 功能是負責資料處理,內嵌了 orm框架 v全拼為 view 功能是接收 業務處理,返回 t全拼為 template 功能是負責封裝構造要返回的 html 內嵌...