在使用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) # 🚀 这里将产生数据库查询
- post_list是QuerySet对象,但尚未访问数据库
- 然而,当使用数据时 查询实际上会执行
✅ 这就是"延迟评估" (Lazy Evaluation)!
2️⃣ 立即评估(Eager Evaluation)是什么?
"即时获取数据并转换为列表或变量!"
要打破延迟评估并立即执行QuerySet,可以使用立即评估(Eager Evaluation)。
✅ 示例: 立即评估
post_list = list(Post.objects.filter(status='PB')) # ✅ 立即执行数据库查询 print(post_list) #
[<Post: Post 1>, <Post: Post 2>] # 🚀 返回的是实际对象列表,而不是QuerySet!
📌 应用立即评估后:
- QuerySet被转换为列表,并立即获取数据
- 无法再使用Django ORM功能(
.filter()
,.annotate()
)
3️⃣ `.values()`和`.values_list()`的立即评估
.values()
和.values_list()
通常保持延迟评估,但是,
如果将其用list()
包裹,将会应用立即评估。
✅ 保持延迟评估
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'}] # 🚀 已立即评估(转换为列表)
✅ 现在已变为列表,无法再使用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() |
优点 | 避免不必要的数据库查询,节约内存 | 在数据库查询后快速利用数据 |
缺点 | 可能会在每次需要时执行查询 | 数据库负载立即产生,无法进行其他ORM操作 |
使用示例 | .filter() , .annotate() , .order_by() |
list() , .count() , .exists() , .values() |
应用立即评估 (list(QuerySet)
) 将数据立即加载并避免额外的数据库查询!
但是要注意,无法再使用QuerySet功能,因此需要谨慎决定何时应用!
📌 结论
✅ Django的QuerySet默认遵循延迟评估 (Lazy Evaluation)。
✅ 使用立即评估(Eager Evaluation)可以立即从数据库获取数据并将QuerySet转换为列表。
✅ 将.values()
和.values_list()
用list()
包裹将实现立即评估。
✅ 保持延迟评估可以避免不必要的数据库查询,但有时立即评估可能更适合!
댓글이 없습니다.