在使用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()包裹将实现立即评估。
✅ 保持延迟评估可以避免不必要的数据库查询,但有时立即评估可能更适合!

目前没有评论。