在使用Django開發的過程中,您會經常遇到'延遲評估(Lazy Evaluation)'這個術語。
不過,很多人可能對這個概念的具體含義以及它在Django中的運作方式好奇。
在本文中,我們將探討'延遲評估'的含義以及如何在Django ORM中應用它。
1️⃣ 延遲評估(Lazy Evaluation)是什麼?
「在需要之前不從資料庫中獲取數據!」
Django的QuerySet基本上遵循延遲評估(Lazy Evaluation)。
也就是說,即使創建了QuerySet,除了實際請求數據之前,查詢不會被執行。
✅ 示例:延遲評估
from myapp.models import Post
# 創建QuerySet(尚未從資料庫中獲取數據)
post_list = Post.objects.filter(status='PB')
print(post_list)
# <QuerySet [ ]># ✅ 尚未執行查詢
# 🔥 當實際請求數據時查詢被執行
for post in post_list:
print(post.title) # 🚀 此時會發生DB查詢
- post_list是QuerySet對象,但尚未訪問資料庫
- 但是在使用數據時,查詢才會被執行
✅ 這就是「延遲評估」(Lazy Evaluation)!
2️⃣ 立即評估(Eager Evaluation)是什麼?
「立即獲取數據並轉換為列表或變數!」
要突破延遲評估使QuerySet立即執行,可以使用立即評估(Eager Evaluation)。
✅ 示例:立即評估
post_list = list(Post.objects.filter(status='PB')) # ✅ 立即執行DB查詢 print(post_list) #
[<Post: Post 1>, <Post: Post 2>] # 🚀 返回的不是QuerySet,而是真實對象列表!
📌 應用立即評估後:
- QuerySet會轉換為列表,數據立即獲取
- 不再能使用Django ORM功能 (
.filter()
,.annotate()
)
3️⃣ `.values()`和`.values_list()`的立即評估
.values()
和.values_list()
基本上保持延遲評估,但是,
將其包裹在list()
中則會應用立即評估。
✅ 保持延遲評估 (Lazy Evaluation)
post_list = Post.objects.filter(status='PB').values("id", "title")
print(post_list)
# <QuerySet [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]> # QuerySet對象
🚨 在此狀態下仍然是QuerySet,因此每次使用數據時都會進行評估。 🔥 已應用立即評估
post_list = list(Post.objects.filter(status='PB').values("id", "title"))
print(post_list)
# [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}] # 🚀 已經是立即評估(轉換為列表)
✅ 現在成為列表而不是QuerySet,並且無法使用Django ORM功能(.filter()
, .annotate()
)。 ✅ 但由於提前獲取了數據,所以之後可以快速使用而無需訪問資料庫。
4️⃣ QuerySet中的.count()
和.exists()
會立即評估!
Django QuerySet基本上是延遲評估,但某些方法會自動執行立即評估。
.count()
(立即執行查詢)
post_count = Post.objects.filter(status='PB').count()
# ✅ 立即執行查詢(SELECT COUNT(*) FROM post WHERE status='PB';)
.exists()
(立即執行查詢)
has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ 立即執行查詢(SELECT 1 FROM post WHERE status='PB' LIMIT 1;)
.count()
和.exists()
會不改變QuerySet立即執行。
5️⃣ 延遲評估與立即評估的比較總結
延遲評估 (Lazy Evaluation) | 立即評估 (Eager Evaluation) | |
---|---|---|
描述 | 在需要之前不執行查詢 | 立即執行查詢並獲取數據 |
示例 | 保持QuerySet 狀態 |
list(QuerySet) , .values_list() , .count() |
優點 | 避免不必要的DB查詢,節省內存 | 數據查詢後可以迅速利用 |
缺點 | 每次可能執行查詢 | 立即對DB造成負擔,無法進行額外的ORM運算 |
使用示例 | .filter() , .annotate() , .order_by() |
list() , .count() , .exists() , .values() |
應用立即評估(list(QuerySet)
)後,數據將立即加載,並且可以避免額外的DB查詢!
但無法再使用QuerySet功能,因此必須謹慎決定何時應用!
📌 結論
✅ Django的QuerySet基本上遵循延遲評估 (Lazy Evaluation)。
✅ 使用立即評估(Eager Evaluation)可以立即從DB獲取數據,並將QuerySet轉換為列表。
✅ 將.values()
和.values_list()
包裹在list()
中則會導致立即評估。
✅ 保持延遲評估可以避免不必要的DB查詢,但有時立即評估可能更合適!
Add a New Comment