在使用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查詢,但有時立即評估可能更合適!

目前沒有評論。